UITableView insertRowsAtIndexPaths 抛出 __NSArrayM insertObject:atIndex:'object cannot be nil' 错误
Posted
技术标签:
【中文标题】UITableView insertRowsAtIndexPaths 抛出 __NSArrayM insertObject:atIndex:\'object cannot be nil\' 错误【英文标题】:UITableView insertRowsAtIndexPaths throwing __NSArrayM insertObject:atIndex:'object cannot be nil' errorUITableView insertRowsAtIndexPaths 抛出 __NSArrayM insertObject:atIndex:'object cannot be nil' 错误 【发布时间】:2014-03-05 17:47:59 【问题描述】:我正在尝试将项目动态插入到我的表格视图中。我的应用程序有一个聊天部分,它在第 0 部分显示旧的(在初始化视图控制器之前从服务器加载)消息,并在第 1 部分显示刚刚发送/接收的消息(最初为零)。加载视图时,所有“旧”消息都已加载并显示,没有问题。当我尝试插入行时,问题就开始了。这是我正在做的事情:
我首先通过添加一个额外项来更新我的表格视图的数据源:[newMessages addObject:newMessage];
(newMessage 是我的自定义消息对象的一个实例,newMessages 是我的数据源)。我验证我的数据源现在有 1 项(添加前为 0)。
然后我调用以下代码:
[self.chatTableView beginUpdates];
[self.chatTableView insertRowsAtIndexPaths:@[[NSIndexPath
indexPathForRow:newMessages.count - 1 inSection:1]]
withRowAnimation:UITableViewRowAnimationBottom];
[self.chatTableView endUpdates];
我的应用程序在 endUpdates
方法处崩溃,给我这个错误:*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
我立即检查了newMessage
是否为nil
,它不是 nil
(并重新检查了我的数据源)所以数据源不是问题。我认为indexPathForRow:newMessages.count - 1
可能是问题所在,并尝试了不同的值(count - 2、count、count + 1),以防万一我遗漏了什么。在这些情况下,我收到另一个错误:'NSInternalInconsistencyException', reason: 'attempt to insert row 1 into section 1, but there are only 1 rows in section 1 after the update'
。错误说明了一切,所以问题也不在于indexPathForRow:newMessages.count - 1
。
我在-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法中添加了断点,以查看它何时被准确调用以及返回什么。似乎根本没有调用该方法,断点没有命中(它确实在第一次加载视图并正确加载初始数据时命中,并且我没有在任何地方设置数据源,因此委托/数据源也已连接正确)。我立即检查了其他方法:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 2;
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
if(section == 0)
return @"Eski mesajlar";
else
return @"Yeni mesajlar";
这些方法返回正确的值。我在-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
中放置了一个断点,以查看它何时被调用。它显然 是 在 [self.chatTableView endUpdates];
方法内调用的(从线程/队列的调用堆栈中可以看出),但随后 [self.chatTableView endUpdates];
立即抛出错误,甚至没有进入 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
方法。我见过一些例子(以及其他一些例子),例如:
我已经阅读了那里的答案,但没有一个对我有帮助。我做错了什么?
【问题讨论】:
【参考方案1】:您是否实施了tableView:estimatedHeightForRowAtIndexPath:
?我在我自己的一个使用NSFetchedResultsController
的应用程序中注意到了一个类似的问题,当调用tableView:endUpdates
时,应用程序会崩溃并显示相同的错误消息。注释掉 tableView:estimatedHeightForRowAtIndexPath:
为我修复了它。
【讨论】:
没错。我有那个方法,并评论它解决了这个问题。谢谢,我可能永远也想不通,我会向 Apple 提交错误报告。 我没有使用获取的结果控制器,而是基于网络数据,我可以确认注释掉估计的高度部分也阻止了我的崩溃。 这个答案救了我的命!解决了崩溃并使插入动画更加流畅!谢谢! 当您删除tableView:estimatedHeightForRowAtIndexPath:
方法(或停止使用estimatedRowHeight
属性)时,请确保您完全了解自己在做什么。您现在强制表格视图为表格视图中的 每一 行调用 tableView:heightForRowAtIndexPath:
,然后在每次调用 reloadData
或类似内容时显示任何内容和 - - 主要的性能影响!因此,删除行高估计的使用并不是一个真正的修复,只是一个似乎是 Apple 错误的解决方法。 (@CanPoyrazoğlu 你有你提交的错误的雷达吗?)
我认为这个“错误”没有完全解决,因为我遇到了相同的崩溃/异常问题并注释掉 tableView:estimatedHeightForRowAtIndexPath: 使它消失(但使 tableView 滚动生涩且无法使用.)【参考方案2】:
关于删除/注释掉 tableView:estimatedHeightForRowAtIndexPath:
,这不是我解决它的方法,因为我的委托没有那个方法。
相反,我实际上在我的viewDidLoad
中设置了tableView.estimatedSectionHeaderHeight = 10.;
。通过简单地注释该行,异常不再发生,然后按我的预期工作。
不过,这太糟糕了,因为我无法说明为什么将其注释掉(或 estimatedHeightForRowAtIndexPath:
方法)会修复它。
【讨论】:
这对我有帮助,删除了任何tableView.estimatedSectionHeaderHeight
和 tableView.sectionHeaderHeight
呼叫为我解决了这个问题。这不是他们第一次给我带来麻烦了……我只是从现在开始假装他们不存在,因为他们只会破坏东西……
这也为我解决了这个问题,在 iOS 9.2 上(!)
亲爱的主,这也帮助了我!感谢您现有的@speby!我不得不保留rowHeight = UITableViewAutomaticDimension
tho,否则它仍然会失败。
不客气@Gee.E!很高兴我能帮上忙。这是一段时间的实时接收器!【参考方案3】:
我最近解决了这个问题,但没有注释掉 estimatedHeightForRowAtIndexPath:
。我遇到的具体问题是我们的表格有许多不同大小的单元格,所以我们只是在估计中使用了平均大小。修复是为了更好地估计插入单元格的大小。
我的假设是该错误是由表格试图滚动到插入的单元格引起的。显然,当滚动到高度估计过小的插入单元格时,先前估计的 contentSize 会导致问题。
【讨论】:
【参考方案4】:我遇到了这个问题,并通过在表为空时不插入来解决它。换句话说,如果表没有行,则不要使用insertRowAtIndexPaths
。而是将对象添加到您的数组或任何数据源,然后调用[myTableView reloadData]
【讨论】:
【参考方案5】:我相信您的错误在于 tableView:numberOfRowsInSection:
方法。 insertRowsAtIndexPaths
方法会在调用tableView:cellForRowAtIndexPath
之前调用此方法,并且它与数据源不匹配,可能是问题所在。
我看到newMessages
是一个局部变量,所以它可能不同步到从tableView:numberOfRowsInSection:
方法返回的数组。
要解决此问题,只需确保 tableView:numberOfRowsInSection 在更新时返回正确的数字即可。
另外:即使 newMessages 为 nil,count 方法也会返回 0 - Objective-C 就是这样工作的。
【讨论】:
以上是关于UITableView insertRowsAtIndexPaths 抛出 __NSArrayM insertObject:atIndex:'object cannot be nil' 错误的主要内容,如果未能解决你的问题,请参考以下文章
UItableview 单元格的动态高度与 UItableview 单元格内的 UItableview
水平 UITableView 中的垂直 UITableView
如何与重叠显示的 UITableView 交互另一个 UITableView