UITableView的数据源同步问题

关于UITableView的数据源同步问题呢,在实际的开发过程当中,比如说新闻资讯类的APP,常见的,比如说腾讯新闻,今日头条,包括微博等APP当中都会涉及到关于数据源同步的问题。比如说我们现在有一套table view的一个数据列表,如果说我们正常对其进行一个删除操作,实际的场景呢?比如说就是插入的一条广告,我们需要把它擦掉,那这就是一个典型的删除操作。
而这一步骤呢,之后可能又会触发一个load more, 也就是我们所说的后向刷新。而删除操作往往是在主线程当中,因为是用户的一个交互动作,而load more往往是在子线程当中去进行这个实际的后向刷新网络请求,这就涉及到了多线程对共享数据的一个访问。我们需要考虑关于数据源的一个同步的问题。那关于这种同步问题应该怎样解决呢?
面试过程当中就会问这样的一道问题,请同思考一下如何解决这种UITableView在多线程环境下去修改或者说访问它的数据源。这么样的一个同步问题主要有两种解决方案, 第一种并发访问,数据拷贝。
那么我们来看一下这种方案的一个实现的时序图

截屏2025-02-08 20.16.26.png

比方说现在有主线程和子线程,那么我们在做数据拷贝的时候,一般是在主线程当中拷贝之后,会把拷贝的结果给子线程来使用。同时在子线程当中进行新数据的网络请求,包括数据解析以及预排版等内容。之后呢,我们假如说在这个子线程进行网络请求,或者说数据解析的过程当中,我们在主线程当中删除了一行数据reload UI之后,这条数据就消失不见了。如果说此时还有时间,主线程可能还会做一些其他的任务。之后这个子线程会返回请求的结果又重新reload一下这个主线程。那么如果说我们子线程使用的是曾经主线程当中的一个数据拷贝,那么它拷贝的时机呢,是在删除一行数据之前,也就是说子线程当中返回给主线程的数据源列表当中仍然包含删除之前的这行数据。此时就会产生异常,也就是我们之前删除的数据又重新出现了。
为了解决这种数据源的同步问题我们看下面的时序图

image.png

我们可以在这个主线程当中进行删除操作的时候,把它记录下来之后,我们在子线程将要返回数据去更新主线程UI的时候同步一下删除操作。在子线程当中,把拷贝过来的这个数据里面被删除的数据,我们在这里面也做一次删除操作,然后再回到主线程去reload UI,就可以保证数据源是同步的。那这种方式呢,就是关于并发访问数据拷贝的这种解决方案。

第二种解决方案呢,关于串行访问这样的一个解决方案,我们同样也通过一幅时序图来解释,
image.png

串行访问的一个过程,比如说有主线程和子线程,既然是串行访问的,我们就要使用到GCD当中的一个串行队列。此时,比如说子线程当中,正在进行网络请求和数据解析,然后呢,他会把这个网络数据请求回来,这一部分的在这个串行队列当中去进行新增数据的预排版。当然了,这一过程是在这个子线程当中去进行的,如果说在这个过程当中,在主线程里面删除某一行数据,它是需要以这个同步的方式去在串行队列当中去进行处理。那么这个过程当中,如果说子线程正在这个串行队列当中去进行新增数据预排版等操作的时候,主线程需要等待一小会儿,然后呢,在主串行队列当中。前一个block任务执行完成之后,然后再去同步主线程发送过来的这个任务数据删除,把数据删除操作同步之后,然后呢,再去回到主线程去更新UI,这样的话就可以保证我们不论是在主线程还是子线程。对于TableView的数据源的操作呢,都是在串行队列上面去进行的,那就可以保证我们这个数据源的一个同步的问题,避免UI刷新错乱的一个现象,那就是关于数据源同步解决方案的第二种串行访问。

两种方案各有利弊,比如说串行访问方式呢,就要求如果说在子线程处理任务特别耗时的时候,我们某一个删除动作可能会有一定的延时,而对于并发访问数据拷贝的那种方式呢。那可能就会有这个数据的一个同步的操作,或者说记录同步的删除的动作,然后呢,我们还需要进行这个大量的数据源的拷贝,对内存的开销上面是有一定的问题,所以在具体的场景当中呢。应该根据实际业务去选择使用哪种方案

那么在面试过程当中呢,我们关于数据源同步这种解决方案呢,主要就有两点:并发访问,数据拷贝和串行访问两种方案。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容