在 iOS 7 beta 5 以及之后的版本,包括 iOS 7 GM/Release 版本中,我开始在日志中看到这个错误,而在我的应用程序中从未在 iOS 6 或更早的 iOS 7 beta 版本中出现过。经过许多尝试,我找到了原因:
我在我的节标题视图中使用 UITableViewCell
对象,并在 tableView:viewForHeaderInSection:
中返回它们。这似乎是常见的做法,特别是自从 iOS 5 开始,使用 Interface Builder 在 StoryBoard 中设计部分标题视图作为原型表视图单元格变得容易。
当我改用普通的 UIView
子类来做节标题视图时,错误消失了,更重要的是,我的表视图停止了随机删除节标题!
看起来(自 iOS 7 beta 5 以来),UITableView
内部维护着其视图层次结构中所有 UITableViewCell
对象及其各自的索引路径的映射关系。由于节标题(或表视图头部和尾部)没有索引路径,如果您为这些视图使用 UITableViewCell
对象,则当表视图发现一个没有索引路径的 UITableViewCell
时,它将变得混乱,导致“no index path for table cell being reused” 错误,并且,如果你不幸的话,会在你的表视图中显示故障:
更新: 如果您可以访问 Apple Dev 论坛,请参考这个主题(我发起的):https://devforums.apple.com/message/882042#882042
如该主题所建议的那样,如果您不想进行太多的重构,可以创建一个围绕着您的 UITableViewCell
的 UIView
包装器,并将其作为节标题视图返回。
UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
[view addSubview:cell];
return view;
请注意,然而这种“包装器” UIView
方法在AutoLayout和设备旋转方面并不兼容,因此建议您使用一个UIView
子类来创建标头和尾部单元格,而不是像答案中的主要部分所解释的那样使用UITableViewCell
子类。
return cell.contentView;
UIView
子类作为标题/页脚单元格,而不是 UITableViewCell
子类。这种方法始终有效,即使使用 AutoLayout (@BartvanKuik)。 UIView
包装器解决方案是一种快速修复的替代方法。 - mluisbrownUITableViewCell
的view
,请将其应用于contentView
,这样它应该会正确显示,至少对我来说是一个简单的解决方法。如果您已经在故事板中将您的部分标题连接为单元格,则此答案是一个更容易的解决方法。 - RyJ我遇到了同样的问题,并花费了几个小时来查找问题。结果发现我在设置单元格时调用了[textField becomeFirstResponder]
(此处textField是自定义tableviewcell的一部分),而[textField becomeFirstResponder]
会发布keyboardWillShow通知,从而导致tableview过早地加载自己,因此引起了臭名昭著的“no index path for table cell being reused”消息。一旦我删除了那个调用,问题就消失了。
dispatch_async(dispatch_get_main_queue(), { self.textField.becomeFirstResponder() })
,然后问题就消失了。 - juanjo除了已被接受的答案(mluisbrown)之外,我还需要为标题单元格添加一个自动调整大小的掩码,因为我的标题包含多行标签,即:
UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
cell.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[view addSubview:cell];
return view;
UIView
包装器,最好将您的标题/页脚单元格制作为 UIView
子类,而不是 UITableView
子类。这样,您就不必添加自动调整大小掩码。 - mluisbrown这是一个内部的UIKit bug,正如苹果公司自己的开发者论坛中所提到的。据说在新版本的Xcode中已经修复了这个问题,尽管我没有找到哪个版本可以修复此问题。
-(void)setEditing:animated:
花费了太长时间来返回。- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self someAdditionalCode];
}
我通过将其更改为以下内容来修复它:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
// DRM: we want to perform the actions from this block in the main thread, but
// asynchronously to avoid excessive delays which were causing issues.
//
dispatch_async(dispatch_get_main_queue(), ^void()
{
[self someAdditionalCode];
});
}
在 resignfirstresponder 后执行我的 endupdates 解决了我的问题(在自定义单元格中有一个 UITextFIeld)
-(void)textfieldEditDone
{
....
[textField resignFirstResponder];
[self.tableView endUpdates];
我曾经遇到过同样的问题,出现了错误提示信息。据我观察,这是由于从一个函数中重新加载表视图造成的,该函数是作为文本框委托协议的一部分被调用的。也就是说textFieldDidEndEditing -> [controller.tableview reload...]
顺便说一下,我在iOS 6上运行时也遇到了这个消息。看起来某些代码继承或导入了类似于以下内容的东西:
(NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section {
NSInteger rows = 0;
if ([delegate respondsToSelector:@selector(numberOfItemsInSection:)]) {
rows = [delegate numberOfItemsInSection:section];
[tableView beginUpdates];
[tableView endUpdates];
}
}
self.tableView beginUpdates;
self.tableView endUpdates;
dispatch_async(dispatch_get_main_queue(), ^(void){
[self.tableView beginUpdates];
[self.tableView endUpdates];
});
NSArray *nibObjects = [[NSBundle mainBundle] loadNibNamed:@"SectionHeader" owner:self options:nil]; SectionHeaderView *sectionHeaderView = nib[0];
据我所知,在StoryBoard中你不能创建一个不是视图控制器的独立视图。 - mluisbrownUIView
,然后将您的UITableViewCell
对象作为子视图添加到其中,从而为节标题单元格创建一个UIView
包装器。 - mluisbrown返回cell.contentView;
- Andrew Duncan