UITableViewController
当返回的行数numberOfRowsInSection
与数据源不一致时,这里有很多关于 s 崩溃的问题。
由于这个问题,我的应用程序崩溃了——但我不明白为什么。更令人困惑的是,它在真正的 iPhone 和 iPhone Simulator 上崩溃,但在(真正的)iPad 上完美运行。
这是错误:
2013-04-05 14:38:15.644 JobTime[28484:c07] *** Terminating app due to uncaught
exception 'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]:
index 3 beyond bounds [0 .. 2]'
没错——NSArray 只扩展到 2。
奇怪的是,TableView 在刷新之前似乎没有向我的控制器(设置为它的委托)询问该部分中的行数。这是我的方法:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(@"called numberOfRowsInSection");
return [[[JobStore sharedStore] allJobs] count];
}
这是 iPhone 模拟器(但不是 iPad)上崩溃的顺序:
- TableView 工作正常,一切正常,上面的 NSLog 消息定期弹出。
- 单击“添加新项目”按钮。
- 将新项目添加到 JobStore(包含作业 NSArray 的单例)。
- 打开一个模式 navigationController (UIModalPresentationFormSheet) 以编辑该新项目。
- 取消编辑 - 并从 JobStore 中删除不需要的项目。
然后崩溃:
- TableView 在不调用 numberOfRowsInSection 的情况下自行更新(即没有出现上面的 NSLog 消息),因此它尝试从 JobStore 中检索数组边界之外的对象。
我已将 NSLog 添加到在 ViewController 被关闭时执行的dismissBlock:
[jobDetailViewController setDismissBlock:^{
NSLog(@"dismissBlock");
[[self tableView] reloadData];
[self clearTableViewBackgroundColorAndResetHighlight];
}];
当我选择“完成”并从模式视图中保存项目时执行,但当我选择“取消”时不会执行。两种方法的代码行相同,我知道每个按钮都调用了正确的方法:
[[self presentingViewController] dismissViewControllerAnimated:YES completion:dismissBlock];
如果我将dismissBlock 简化为仅一个NSLog 语句而没有其他调用,情况也是如此:在“取消”情况下不会调用它。
我发现的唯一解决方案是在 cellForRowAtIndexPath 中重新检查数组的边界相当不雅:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1
reuseIdentifier:@"UITableViewCell"];
}
// Check array bounds before trying to retrieve object from array
if ([indexPath row] < [self tableView:tableView numberOfRowsInSection:0]) {
Job *j = [[[JobStore sharedStore] allJobs] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[j displayDescription]];
[[cell detailTextLabel] setText:[j timeDescription]];
if ([j selected]) {
[cell setBackgroundColor:[UIColor lightGrayColor]];
}
} else {
[[cell textLabel] setText:@""];
NSLog(@"gone past array bounds");
}
return cell;
}
这行得通,但它很笨拙。知道为什么 TableView 在刷新之前似乎不要求更新的行数吗?或者为什么它可以在 iPad 上运行,而在 iPhone 上不行?
我开始怀疑不同模式视图的一些怪癖,但如果有任何帮助,我将不胜感激。提前致谢。
詹姆士