“这是什么意思?”;没有重复使用的表单元格的索引路径;iOS 6/7中的消息?

“这是什么意思?”;没有重复使用的表单元格的索引路径;iOS 6/7中的消息?,ios,ios6,uitableview,ios7,Ios,Ios6,Uitableview,Ios7,自从开始使用iOS 6(以及iOS 7)编译我的应用程序以来,我开始看到这条消息。我知道UITableViews管理单元的方式在iOS 6中有所不同,但我不需要修改代码使其继续工作。但我担心这条信息可能指向一些我还没有看到的潜在问题。 有人能解释一下吗?这是一个内部UIKit错误——正如苹果自己的开发论坛所提到的。虽然我找不到关于哪个版本修复了这个问题的信息,但它应该在更新版本的xcode中得到修复。作为我之前文章的补充(我在文章中提到这显然是UIKit的一个bug),我能够找到一个解决我的特殊

自从开始使用iOS 6(以及iOS 7)编译我的应用程序以来,我开始看到这条消息。我知道UITableViews管理单元的方式在iOS 6中有所不同,但我不需要修改代码使其继续工作。但我担心这条信息可能指向一些我还没有看到的潜在问题。
有人能解释一下吗?

这是一个内部UIKit错误——正如苹果自己的开发论坛所提到的。虽然我找不到关于哪个版本修复了这个问题的信息,但它应该在更新版本的xcode中得到修复。

作为我之前文章的补充(我在文章中提到这显然是UIKit的一个bug),我能够找到一个解决我的特殊情况的方法(其中的信息与桌子上一些奇怪的视觉故障有关)

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

作为记录,我在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:序列时,问题神奇地消失了。

从iOS 7 beta 5开始,我开始在日志中显示此错误,包括在iOS 7 GM/发布版本中,而在iOS 6或更早的iOS 7 beta中我的应用程序中从未出现过此错误。经过大量实验,我发现了原因:

我使用了
UITableViewCell
对象作为我的节头视图,并在
tableView:viewForHeaderInSection:
中返回它们。这似乎是常见的做法,尤其是在iOS 5之后,当使用Interface Builder将节头视图设计为故事板中的原型表视图单元格变得很容易

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

似乎(从iOS 7 beta 5开始)
UITableView
正在内部维护其视图层次结构中所有
UITableViewCell
对象及其各自的索引路径的映射没有索引路径,如果对这些视图使用
UITableViewCell
对象,则当表视图发现它没有索引路径的
UITableViewCell
时,它会感到困惑,从而导致“没有重用表单元格的索引路径”错误,如果不走运,则会在表视图中显示小故障:

更新:如果您可以访问苹果开发人员论坛,以下是关于它的帖子(我从这里开始):

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

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

return view;

但是请注意,这个“包装器”
UIView
方法无法很好地处理自动布局和设备旋转,因此我建议您对页眉和页脚单元格使用
UIView
子类,而不是回答的主要部分中解释的
UITableViewCell
子类。

我在出现错误消息时也遇到了同样的问题。就我所见,是这样的由于从textfield作为其委托协议的一部分调用的函数重新加载表视图而导致。即textFieldDidEndEditing->[controller.tableview reload…]

我也遇到了同样的问题,我花了几个小时才找到问题。结果证明,我在设置单元格时调用了
[textfield becomeFirstResponder]
(此处textField是自定义tableviewcell的一部分);
[textField becomeFirstResponder]
反过来,posts键盘将显示通知,从而导致tableview自身过早加载,从而导致臭名昭著的“没有重复使用表单元格的索引路径”消息。一旦我删除了该调用,问题就消失了。

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

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

好吧,我只是用了一天中最好的时间来试图弄明白这一点,所以希望这个替代解释能为其他人节省一些时间

我有一个tableview,它在加载时有时会发出此消息。它是由核心数据对象的KVO通知在加载视图时触发引起的。(在观察到更改时,我的控制器尝试在有问题的tableview上调用reloadData。修复方法是在视图完成加载之前不观察对象。)(之前,我通过访问器分配对象后就开始观察对象)


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

这可能对某人有所帮助:我曾经在刷新单个表视图单元格时出错。 我本想做点像这样的事

NSIndexPath *reloadRow = [NSIndexPath indexPathForRow:1 inSection:2];
[self._mainTableView reloadRowsAtIndexPaths:@[reloadWebViewRow]
                           withRowAnimation:UITableViewRowAnimationFade];
但是不小心,我打了

NSIndexPath *reloadRow = [NSIndexPath indexPathForItem:1 inSection:2];
请注意两个IndExpath的区别:一个是使用
indexPathForItem
创建的(错误),另一个是使用
indexPathForRow
(正确)。
这一切都导致了tableView的异常行为和标题中的错误消息。

在FirstResponder辞职后执行EndUpdate解决了我的问题(在我的自定义单元格中有一个UITextFIeld)


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

return cell.contentView;

我的问题似乎是在尝试更新web调用回调代码部分中的UI时触发的。我通过强制在主线程上进行UI更新来解决问题。我使用的代码如下所示

void runOnMainQueueWithoutDeadlocking(void (^block)(void)){
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}
我把它称为成功块内部的
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];
});
self.tableView beginUpdates;
self.tableView endUpdates;
dispatch_async(dispatch_get_main_queue(), ^(void){
                            [self.tableView beginUpdates];
                            [self.tableView endUpdates];
});
func tableView(tableView: UITableView,
               titleForHeaderInSection section: Int) -> String? {
    return ""
}