为什么我的数组加载,但我的表视图会崩溃,索引超出空数组的界限



这是我的错误:

-[__NSArrayM objectAtIndex:]: index 12 beyond bounds for empty array

我知道此错误意味着我正在尝试访问"空数组"。

此错误仅在从视图 Y 弹出时在 viewX 中发生。当您在viewY中按导航栏上的"后退按钮"并立即滚动表格视图时,它将崩溃并导致此错误。我正在使用 RETableViewManager 来加载我的表视图。

在viewX的viewDidLoad中:

[[RACSignal combineLatest:@[RACObserve(self, record), RACObserve(self, restaurant)]] subscribeNext:^(id x) {
       [self setupItems];
    }];

在设置项中:

RecordManager *recordManager = [[EZRecordManager alloc] initWithRecord:self.record restaurant:self.restaurant sender:self.navigationController];
self.items = [recordManager items];
self.section = [RETableViewSection section];
[self.items each:^(id data) {
    if ([data isKindOfClass:[NSString class]]) {
        self.navigationItem.title = (NSString *)data;
    } else {
        [self registerItem:[data class]];
        [self.section addItem:data];
    }
}];
[self.manager addSection:self.section];
[self.tableView reloadData];

我NSLoged了我的数组'self.items'。 这是根据方法记录的内容:

viewDidAppear - (
"U5df2U8a02U4f4dUff0cU5c1aU672aU7528U9910",
"<REReservationHeaderItem: 0x14015b0b0>",
"<REAttributedStrItem: 0x14015b1b0>",
"<REAttributedStrWithNextItem: 0x140191a70>",
"<REAttributedStrItem: 0x140193f60>",
"<RESpacerItem: 0x140194870>",
"<REAttributedStrWithNextItem: 0x14019ce10>",
"<REAttributedStrItem: 0x140199230>",
"<RESpacerItem: 0x1401a04e0>",
"<REActionItem: 0x14019e490>",
)

NSLog 在 setupItems 中记录相同的数组,所以我知道该数组仍然存在,因为 self.item 保存为属性:

@property (nonatomic, strong) NSArray *items;

因此,当我第一次加载 viewX 时,此算法按预期工作,但是一旦我进入另一个视图(viewY)并按 viewY 上的"后退按钮"弹出到 viewX,然后立即滚动,它就会崩溃并出现上述错误。如果我等待一秒钟(甚至半秒钟),viewX 将正常工作并且没有问题。我知道这是次要的,但我的总理强调这不应该发生。如何解决这个问题?

发生错误的方法(RETableViewManager 库的一部分):

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

{ RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row];

UITableViewCellStyle cellStyle = UITableViewCellStyleDefault;
if ([item isKindOfClass:[RETableViewItem class]])
    cellStyle = ((RETableViewItem *)item).style;
NSString *cellIdentifier = [NSString stringWithFormat:@"RETableViewManager_%@_%li", [item class], (long) cellStyle];
Class cellClass = [self classForCellAtIndexPath:indexPath];
if (self.registeredXIBs[NSStringFromClass(cellClass)]) {
    cellIdentifier = self.registeredXIBs[NSStringFromClass(cellClass)];
}
if ([item respondsToSelector:@selector(cellIdentifier)] && item.cellIdentifier) {
    cellIdentifier = item.cellIdentifier;
}
RETableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
void (^loadCell)(RETableViewCell *cell) = ^(RETableViewCell *cell) {
    cell.tableViewManager = self;
    // RETableViewManagerDelegate
    //
    if ([self.delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willLoadCell:forRowAtIndexPath:)])
        [self.delegate tableView:tableView willLoadCell:cell forRowAtIndexPath:indexPath];
    [cell cellDidLoad];
    // RETableViewManagerDelegate
    //
    if ([self.delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didLoadCell:forRowAtIndexPath:)])
        [self.delegate tableView:tableView didLoadCell:cell forRowAtIndexPath:indexPath];
};
if (cell == nil) {
    cell = [[cellClass alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier];
    loadCell(cell);
}
if ([cell isKindOfClass:[RETableViewCell class]] && [cell respondsToSelector:@selector(loaded)] && !cell.loaded) {
    loadCell(cell);
}
cell.rowIndex = indexPath.row;
cell.sectionIndex = indexPath.section;
cell.parentTableView = tableView;
cell.section = section;
cell.item = item;
cell.detailTextLabel.text = nil;
if ([item isKindOfClass:[RETableViewItem class]])
    cell.detailTextLabel.text = ((RETableViewItem *)item).detailLabelText;
[cell cellWillAppear];
return cell;

}

通常,当"稍等片刻解决问题"时,这是因为您遇到了异步问题。

首先要检查的内容

确保在向后移动时调用重新加载代码。也许您的表视图没有被清空,但数组被清空了。向后移动将允许您滚动旧内容(仍加载),但委托方法将无法创建新单元格,因为数组现在为空。

如果您等待,您的异步方法将完成它的工作,并且数组现在再次已满,这使得一切正常。

可能的解决方案:

清空,然后在 viewWillAppear 中重新加载表视图。这将导致表视图的视觉闪烁变为空,然后再次充满。它还会将您滚动到第一个元素。话虽如此,它真的很容易和快速,并且使用微调器它会看起来更流畅。

其他可能的解决方案:

离开页面后保持加载的数据,因此当您返回时,它仍然存在。您可以使用任何可以在应用程序中保持数据加载的内容。它可以是一个保持实例化的单例类,或者保存在数据库中并从中重新加载(它比直接从互联网加载要快得多),或者你能想到的任何内容。

最新更新