reloadData同步问题

时间:2011-04-19 11:40:39

标签: objective-c uitableview synchronization reloaddata

所以这是我的问题。 在我的应用程序主页中,我有一个简单的UITableView,最多可容纳3个部分,2个部分,每个部分最多3个项目,第3个部分最多可容纳6个项目。

每个部分都有与之关联的标题。

实际内容来自web,我发出请求,服务器发送数据,我用NSXMLParser解析响应,创建数组以保存每个部分的数据(3个数组),并创建另一个数组以保持对我将不得不展示。

然后,最后,我调用[myTableView reloadData]来刷新内容和重绘表。 用户还可以自己刷新内容。为此,我正在使用像Facebook应用程序一样的拉动刷新机制。

使用pull-to-refresh刷新内容也最终调用[myTableView reloadData]。 当我刷新我的内容并且表需要更改其布局时,我遇到了令人讨厌的崩溃(例如:表当前包含所有3个部分,在我重新加载数据之后它将只显示一个部分)。

我使用调试器来追踪问题。这是我发现的:

  1. 用户将整个表格拉下50像素,然后发布
  2. 动画开始使表格“向上”以容纳320x50视图,显示“正在加载”消息+在表格顶部设置动画的UIActivityIndi​​catorView
  3. 刷新被触发,我在后台任务中发出新的web服务请求,获取新数据,解析,更新数组,最后在主线程上执行reloadData
  4. 与此同时,虽然刷新正在做的所有事情,我注意到UITableView STILL将委托消息发送到:
    • 的tableView:viewForHeaderInSection:
    • 的tableView:的cellForRowAtIndexPath:
  5. 我认为这是因为拉动刷新动画会“移动”表格并显示新的单元格/标题,从而调用上述内容。

    问题是这会导致可怕的崩溃,因为保存数据的数组和部分数组本身会同时被修改。

    发生这种情况时,委托方法可能会在错误的上下文中使用更新/尚未更新的项目/部分数组。也就是说,在

    之前
    • numberOfSectionsInTableView:
    • tableView:numberOfRowsInSection:

    有机会为更新的数组正确更新新结构。

    我知道没有任何代码示例的长篇故事,但我想如果我已经知道问题(至少我希望我这样做)并且如果有人看到我的观点,也许有人可以指出我正确的方向来纠正这个同步问题。

    感谢阅读!

    稍后编辑

    我发现了问题所在。我的pull-to-refresh机制使用stopLoading回调,如下所示:

    - (void)stopLoading 
    

    {     isLoading = NO;

    // Hide the header
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationDidStopSelector:@selector(stopLoadingComplete:finished:context:)];
    self.myTableView.contentInset = UIEdgeInsetsZero;
    [refreshArrow layer].transform = CATransform3DMakeRotation(M_PI * 2, 0, 0, 1);
    [UIView commitAnimations];
    

    }

    在某些时候,我重置了我的表的contentInset,将其设置为UIEdgeInsetsZero。 这个以及在主线程上返回后台刷新后我在reloadData之前调用stopLoading的事实 - 在错误的时刻触发了错误的委托回调。

    因此,在更改表的contentInset和reloadData之间存在时间问题。

1 个答案:

答案 0 :(得分:0)

听起来您正在从不同的线程更新用于表视图的数据存储。这不是一个好主意 - 数据很容易进入不一致的状态,而您正在使用的容器可能不是线程安全的。

正确的方法是仅从主线程更新此数据。此外,您可能希望查看插入行等的方法,这使得很少需要完全重新加载。如果您只是想因新数据更新一个单元格,那么只需刷新该单元格即可。