是啥导致 cellForRowAtIndexPath 中的 outOfBounds 错误?

Posted

技术标签:

【中文标题】是啥导致 cellForRowAtIndexPath 中的 outOfBounds 错误?【英文标题】:What causes outOfBounds error in cellForRowAtIndexPath?是什么导致 cellForRowAtIndexPath 中的 outOfBounds 错误? 【发布时间】:2018-07-07 00:13:02 【问题描述】:

我遇到了 Crashlytics 提出的以下问题:

[__NSArrayM objectAtIndexedSubscript:]: index 5 beyond bounds for empty array
-TopicListViewController tableView:cellForRowAtIndexPath:]

使用indexPath.row 访问数据源时。

我们有一些异步数据更新来更新数据源,并且该变量是非原子的。

是否有可能在更新数据源时调用cellForRowAtIndexPath?因此导致访问不再存在的索引?

可能是因为变量是非原子的吗?

以下是相关代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    if (indexPath.row > [self.tableData count] - 1 || ![self.tableData isValidArray]) 
        return nil; //Some protection to prevent this issue...
    

    TopicCell * cell = (TopicCell *)[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
    cell.delegate = self;

    NSDictionary * data = nil;

    if (self.we_isSearching) 
        data = self.we_searchResult[indexPath.row];
     else 
        data = [self.tableData objectAtIndex:indexPath.row]; //Crashes here
    

【问题讨论】:

numberOfRowsInSection 方法和cellForRowAt 方法的其余部分更新您的问题。 它清楚地表明您的numberOfRowsInSection 大于您在cellForRowAtIndexPath 中访问的数组的大小,因此它超出了索引并抛出错误。 用'numberOfRowsInSection'方法更新你的代码 【参考方案1】:

"index 5 beyond bounds for empty array" 只是表明您没有初始化数组或者您正在访问的值的范围超出了数组的范围。您正在尝试访问空/具有较少元素的数组或未初始化的数组中的索引 5,这就是为什么它在 cellForRowAtIndexPath 中为您提供“outOfBounds”。

是否有可能在更新数据源时调用 cellForRowAtIndexPath?

是的,cellForRowAtIndexPath 总是会在你看到一个新的 tableview 单元格时被调用,例如当你滚动 tableview 或者你已经添加了某种通知添加到你的数据源或通过重新加载 tableview .

您可以在 cellForRowAtIndexPath 处设置一个断点并检查堆栈跟踪,也许您会得到一些导致 tableview 重新加载的东西。

【讨论】:

您知道防止这种行为发生的方法吗?我觉得比赛条件是导致崩溃的原因。 您必须首先确定何时以及为什么要重新加载 tableview,同时尝试确定您的数据源是否正确,这可能是由于在错误移动时不必要地重新加载 tableview 而发生的.为了防止只是添加并检查您的 cellForRowAtIndexPath 并检查索引是否在您的数据源范围内! 问题是由于异步批量加载大量数据时 we_searchResult 数组的竞争条件引起的。【参考方案2】:

尝试从 self.tableData 计数以返回 numberOfRowsInSection 方法。喜欢

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section      

     return [self.tableData count];

【讨论】:

【参考方案3】:

在 tableView 方法的 numberOfRowsInSection 中传递数组计数。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return array.count;

【讨论】:

【参考方案4】:

你的情况

if (indexPath.row > [self.tableData count] - 1 || ![self.tableData isValidArray]) 

错了。如果有 5 个元素,则最后一个 indexPath.row 将是索引 4,因此具有实际值的条件将是:

if (4 > 5 - 1) --> if 4 > 4

所以有效条件是:

if (indexPath.row >= [self.tableData count] - 1)

但如果条件正确,您将崩溃:

return nil 

因为显然您的数据源与表数据源不同。您的模型数据源应始终与表数据源相同。

【讨论】:

以上是关于是啥导致 cellForRowAtIndexPath 中的 outOfBounds 错误?的主要内容,如果未能解决你的问题,请参考以下文章

是啥导致了这个推进错误?

是啥导致了 NSInvalidArgumentException?

是啥导致移动构造函数被删除

是啥导致系统发出蜂鸣声?

是啥导致 opensuse Docker 膨胀?

是啥导致连接中止?