所以这是我的问题。在我的应用主页中,我有一个简单的 UITableView,它最多可以容纳 3 个部分,2 个部分,每个部分最多 3 个项目,第三个部分最多可以包含 6 个项目。
每个部分都有一个与之关联的标题。
实际内容来自网络,我发出请求,服务器发送数据,我用 NSXMLParser 解析响应,创建数组来保存每个部分的数据(3 个数组),并创建另一个数组来保存我将要引用的部分必须显示。
然后,最后,我调用 [myTableView reloadData] 来刷新内容并重绘表格。用户还可以自己刷新内容。为此,我使用了类似于 Facebook 应用程序的下拉刷新机制。
使用 pull-to-refresh 刷新内容也会调用 [myTableView reloadData]。当我刷新内容并且表格需要更改其布局时,我遇到了严重的崩溃(例如:表格当前包含所有 3 个部分,并且在我 reloadData 后它只会显示一个部分)。
我使用调试器来追踪问题。这是我发现的:
- 用户将整个表格拉下 50 像素然后释放
- 动画开始使表格“向上”以适应 320x50 视图,显示“正在加载”消息 + 在表格顶部动画的 UIActivityIndicatorView
- 触发刷新,我在后台任务中发出新的 Web 服务请求,获取新数据,解析,更新数组,最后在主线程上执行 reloadData
- 与此同时,虽然刷新正在做所有我注意到 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 更改之间的时间问题。