0

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

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

实际内容来自网络,我发出请求,服务器发送数据,我用 NSXMLParser 解析响应,创建数组来保存每个部分的数据(3 个数组),并创建另一个数组来保存我将要引用的部分必须显示。

然后,最后,我调用 [myTableView reloadData] 来刷新内容并重绘表格。用户还可以自己刷新内容。为此,我使用了类似于 Facebook 应用程序的下拉刷新机制。

使用 pull-to-refresh 刷新内容也会调用 [myTableView reloadData]。当我刷新内容并且表格需要更改其布局时,我遇到了严重的崩溃(例如:表格当前包含所有 3 个部分,并且在我 reloadData 后它只会显示一个部分)。

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

  1. 用户将整个表格拉下 50 像素然后释放
  2. 动画开始使表格“向上”以适应 320x50 视图,显示“正在加载”消息 + 在表格顶部动画的 UIActivityIndi​​catorView
  3. 触发刷新,我在后台任务中发出新的 Web 服务请求,获取新数据,解析,更新数组,最后在主线程上执行 reloadData
  4. 与此同时,虽然刷新正在做所有我注意到 UITableView STILL 发送委托消息到:
    • 表视图:viewForHeaderInSection:
    • 表视图:cellForRowAtIndexPath:

我认为这是因为下拉刷新动画将表格“向上移动”并显示新的单元格/标题,从而调用上述内容。

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

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

  • numberOfSectionsInTableView:
  • 表视图: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 更改之间的时间问题。

4

1 回答 1

0

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

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

于 2011-04-19T11:58:37.843 回答