为什么我的数组加载但是我的tableView会因索引超出空数组的边界而崩溃?

时间:2016-01-25 10:31:34

标签: ios objective-c

这是我的错误:

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

我知道这个错误意味着我试图访问"空数组"。

此错误仅在viewX从viewY弹回时发生。当您按下“后退按钮”按钮时在viewY导航栏上并立即滚动tableView,它将崩溃并导致此错误。我使用RETableViewManager加载我的tableView。

在viewX的viewDidLoad中:

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

在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];

我NSLogged我的阵列' self.items'。这是根据方法记录的:

viewDidAppear - (
"\U5df2\U8a02\U4f4d\Uff0c\U5c1a\U672a\U7528\U9910",
"<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)并按下“后退”按钮&#39;在viewY上弹出到viewX然后立即滚动,它崩溃与上述错误。如果我等待一秒钟(甚至半秒钟),viewX将正常工作并且没有问题。我知道这是次要的,但我的PM强调这不应该发生。我该如何解决这个问题?

错误发生的方法(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;

}

1 个答案:

答案 0 :(得分:1)

通常在“等待一点点修复问题”时,这是因为你有一个异步问题。

首先检查

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

如果你等了,你的异步方法就可以了,而且数组现在再次满了,这使得一切正常。

可能的解决方案:

清空然后在viewWillAppear中重新加载tableview。这将导致tableview的视觉闪烁变为空,然后再次满。它还会滚动到第一个元素。话虽如此,它真的很容易和快速,并且使用旋转器它会显得更加平滑。

其他可能的解决方案:

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