这是我的错误:
-[__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 时按预期工作,但是一旦我进入另一个 View (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;
最佳答案
通常当“稍等片刻就能解决问题”时,那是因为您遇到了异步问题。
首先要检查的东西:
确保在您返回时调用重新加载代码。也许您的 tableview 没有被清空,但是数组被清空了。向后移动可让您滚动旧内容(仍在加载),但委托(delegate)方法将无法创建新单元格,因为数组现在为空。
如果您等待,您的异步方法会完成它的工作,并且数组现在又满了,这使得一切正常。
可能的解决方案:
清空然后在 viewWillAppear
中重新加载 TableView 。这将导致 tableview 变空然后又变满的视觉闪光。它还会将您滚动到第一个元素。话虽这么说,它真的很简单和快速,并且使用旋转器它会显得更加流畅。
其他可能的解决方案:
离开页面后保持加载的数据,这样当您返回时它仍然存在。您可以使用任何可以在应用程序中保持数据加载的内容。它可以是一个保持实例化的单例类,或者保存在数据库中并从中重新加载(这比直接从互联网加载快得多),或者您能想到的任何东西。
关于ios - 为什么我的数组加载但我的 tableView 会崩溃,索引超出空数组的范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34990368/