iOS 6/7中“无法使用表格单元索引路径”消息的含义是什么?

时间:2012-10-07 19:38:59

标签: ios ios6 uitableview ios7

自从开始使用iOS 6(以及iOS 7)编译我的应用程序后,我开始看到此消息。我知道UITableViews管理单元格的方式在iOS 6中是不同的,但我不需要修改我的代码以便继续工作。但我担心这条消息可能会指出一些我尚未看到的潜在问题。 任何人都可以放弃任何光明吗?

14 个答案:

答案 0 :(得分:132)

我开始在iOS 7 beta 5以后的日志中显示此错误,包括在iOS 7 GM / Release版本中,但从未在我的iOS 6或早期iOS 7测试版中发生过这种错误。经过大量的实验,我找到了原因:

我使用UITableViewCell个对象作为我的节标题视图,并在tableView:viewForHeaderInSection:中返回它们。这似乎是常见的做法,特别是在iOS 5之后,当使用Interface Builder在StoryBoard中将部分标题视图设计为原型表视图单元时变得很容易。

当我更改我的应用程序以仅使用常规UIView子类作为我的节标题视图时,错误消失了,更重要的是,我的表格视图停止随机删除节标题!

似乎(自iOS 7 beta 5)UITableView在内部维护其视图层次结构中所有UITableViewCell个对象及其各自索引路径的映射。由于节标题(或页脚的表格视图标题)没有索引路径,如果对这些视图使用UITableViewCell对象,则表格视图在找到UITableViewCell时会感到困惑它没有索引路径,导致“没有重复使用表格单元的索引路径”错误,如果你不幸,在表格视图中显示毛刺:

更新:如果您有权访问Apple Dev论坛,请参阅以下内容(我刚开始):https://devforums.apple.com/message/882042#882042

正如该线程中所建议的那样,如果您不想重新考虑很多因素,可以在UIView周围创建一个UITableViewCell包装器,并将其作为节标题视图返回。

UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
[view addSubview:cell];

return view;

但请注意,这种“包装器”UIView方法不能很好地与AutoLayout和设备旋转一起使用,因此我建议您使用UIView子类来表示页眉和页脚单元格,而不是{{1在答案的主要部分中解释的子类。

答案 1 :(得分:41)

我将返回UITableViewCell的contentView,而不是创建一个包装器。在storybord中修复了约束-jabble

return cell.contentView;

答案 2 :(得分:26)

我遇到了同样的问题,花了几个小时才找到问题所在。结果我在设置单元格时调用了[textField becomeFirstResponder](这里textField是自定义tableviewcell的一部分); [textField becomeFirstResponder]轮流发布了keyboardWillShow通知,这反过来导致tableview过早地加载自身,从而导致臭名昭着的“没有索引表单元格的索引路径”消息。一旦我删除了该调用,问题消失了。

答案 3 :(得分:16)

除了接受的答案(mluisbrown)之外,我还需要在标题单元格中添加一个autoresizingMask,因为我的包含一个多行标签,即

UIView *view = [[UIView alloc] initWithFrame:[cell frame]];
cell.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[view addSubview:cell];
return view;

答案 4 :(得分:8)

这是一个内部的UIKit错误 - 正如Apple自己的开发论坛中所提到的那样。它应该在较新版本的xcode中修复,虽然我无法找到有关哪个版本修复此信息的信息。

答案 5 :(得分:4)

作为我上一篇文章的补充(其中我提到这显然是UIKit的一个错误),我能够为我的特定情况找到一个解决方法(其中的消息与一些奇怪的可视化故障有关)表)。

显然我的自定义单元格被覆盖-(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];
    });
}

答案 6 :(得分:2)

出现错误消息时遇到了同样的问题。据我所知,它是由文本字段调用的函数重新加载表视图作为其委托协议的一部分引起的。即textFieldDidEndEditing - > [controller.tableview reload ...]

答案 7 :(得分:2)

在resignfirstresponder解决了我的问题后做了我的最终更新(在我的自定义单元格中有一个UITextFIeld)

-(void)textfieldEditDone
{
....

    [textField resignFirstResponder];
    [self.tableView endUpdates];

答案 8 :(得分:1)

为了记录,我在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];
    }
}

当删除beginUpdate:/ endUpdate:序列时,问题神奇地消失了。

答案 9 :(得分:1)

这显然是一个老问题,但希望这可以帮助那些仍然在iOS8 +中遇到此问题的人,因为这仍然是针对此特定错误消息的首要问题。

我使用PINRemoteImage将图像异步下载到自定义UITableViewCell内的UIImageView。

为了在图像加载后正确调整行的大小(动态高度单元格使用自动布局),我调用了:

self.tableView beginUpdates;
self.tableView endUpdates;

然后我得到了#34;没有索引路径表格单元被重用"消息和应用程序崩溃。我原以为PINRemoteImageManagerResult块在主线程上,但事实证明它不是 - 因此确保在主线程上调用了开始/结束更新来修复问题。

dispatch_async(dispatch_get_main_queue(), ^(void){
                            [self.tableView beginUpdates];
                            [self.tableView endUpdates];
});

答案 10 :(得分:0)

好吧,我只是用了一天中的大部分时间试图解决这个问题,所以希望这个替代解释可以节省其他人一些时间。

我有一个tableview,在加载时会发送此消息有时。事实证明,这是由加载视图时触发的Core Data对象的KVO通知引起的。 (在观察到更改时,我的控制器尝试在相关的tableview上调用reloadData。修复了在视图加载完成之前没有观察对象(之前我开始通过访问器分配对象时开始观察对象)

TLDR:检查您是否尝试从主线程以外的其他位置重新加载数据。

答案 11 :(得分:0)

也许这有助于某人:我在刷新单个表格视图时遇到此错误。 我打算做一些像

这样的事情
NSIndexPath *reloadRow = [NSIndexPath indexPathForRow:1 inSection:2];
[self._mainTableView reloadRowsAtIndexPaths:@[reloadWebViewRow]
                           withRowAnimation:UITableViewRowAnimationFade];

但不小心,我打字了

NSIndexPath *reloadRow = [NSIndexPath indexPathForItem:1 inSection:2];

注意两个索引路径的区别:一个是indexPathForItem(错误)创建的,另一个是indexPathForRow(正确)。 这一切都导致了tableView的非常奇怪的行为以及标题中的错误消息。

答案 12 :(得分:0)

似乎我的问题是在我尝试在代码的一部分内更新UI时触发的,该代码是来自Web调用的回调。我解决了强制UI更新发生在主线程上。我使用了这样的代码。

void runOnMainQueueWithoutDeadlocking(void (^block)(void)){
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

我在后台网络电话的成功模块中将其称为如下。

runOnMainQueueWithoutDeadlocking(^{
    [self.tableView beginUpdates];
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:2] withRowAnimation:UITableViewRowAnimationAutomatic];
    [self.tableView endUpdates];
});

答案 13 :(得分:0)

另一个条件......

发生这种情况时,我不想要标题,而是返回nil

<强>修正:

func tableView(tableView: UITableView,
               titleForHeaderInSection section: Int) -> String? {
    return ""
}