0

我正在构建的应用程序有很多表。我正在加载前 15 行的数据,当用户向下滚动时,我将获得下一批 15 行。

我已经编写了一些接受“计数”和“跳过”的 DBAccess 函数。初始加载表时,count = 15,skip = 0。当用户滚动时,count = 15,skip = [array count];

代码是这样的:

- (void)getDataWithCount:(NSInteger)count withSkip:(NSInteger)skip
{
    if (skip == 0)
        self.dataArray = [[NSMutableArray alloc]init];

    [DBAccess getData:self.dataArray withCount:count withSkip:skip handler:^(void)
    {
        if (no error)
            [table reloadData];
    }]; 
}

在非常慢的网络连接上(例如,索引 16 超出空数组。numberOfRowsInSection 返回 [数组计数])时,我在 cellForRowAtIndexPath 中得到数组越界崩溃。

我认为问题如下:

0) 进入画面。

1)加载15行

2)向下滚动,加载另一个 15。连接速度慢,所以我还没有从我的 sendAsynchronousRequest db 调用中得到回调

3)转到另一个视图控制器(即,离开屏幕。我可以这样做,因为异步不会冻结我的屏幕)。

4) 回到屏幕上。加载初始屏幕设置skip = 0,因此初始化我的可变数组,命中数据库

5) 从第 2 步命中的数据库返回。我的可变数组现在从第 4 步开始设置为零。当重新加载表时,它试图获取 self.dataArray objectAtIndex:16 等,当数组现在从 if(skip == 0)initialise 为空时

这看起来对吗?如果 numberOfRowsInSection 返回 [array count]; 是否有任何其他原因导致我的数组超出范围?有没有首选的方法来解决这个问题?

4

1 回答 1

0

很难说提供的信息有限,但很难协调第 5 点,即您的阵列已重新初始化,但您的数据库请求仍在进行中。如果支持表的模型对象被重置,则数据库查询不应仍在运行。任何一个:

  • 一旦模型对象超出范围,您应该取消异步数据请求(例如,使用操作队列,如果操作是设计属性,则可以取消,而不是 GCD);或者

  • 您应该将该模型对象保存在某种缓存机制中,以便在完成异步数据请求时,当您在步骤 4 中返回控制器时,您已经将数据缓存并准备好显示。

至于其他潜在的问题来源,我想知道您的异步数据更新过程是否真正是线程安全的。您是否正在将您的交互与您正在异步更新的那些属性同步?这种同步通常通过某种锁定机制或通过专用的串行队列(或在读写器模式中使用并发队列)来完成。线程安全是一个非常重要的问题,我想知道你在这方面有多自信。

于 2013-07-03T08:36:23.970 回答