当UITableViewController
返回的行数与数据源不一致时,numberOfRowsInSection
崩溃时有很多问题。
我的应用程序因为这个问题而崩溃 - 但我看不出原因。为了增加混乱,它在真正的iPhone和iPhone模拟器上崩溃,但在(真正的)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)崩溃的顺序:
然后崩溃:
我已经在解除ViewController完成时执行的dismissBlock添加了一个NSLog:
[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?
我开始怀疑不同模态视图的一些怪癖但会感激任何帮助。提前谢谢。
詹姆斯
答案 0 :(得分:0)
UITableView
缓存值,以便它可以更高效(每次询问您可能会很慢 - 取决于您的计算方式)。
因此,如果您更改基础数据源,则需要让tableView
了解它。您可以执行完整[self.tableView reloadData];
或使用以下方法
- insertRowsAtIndexPaths:withRowAnimation:
- deleteRowsAtIndexPaths:withRowAnimation:
- moveRowAtIndexPath:toIndexPath:
- insertSections:withRowAnimation:
- deleteSections:withRowAnimation:
- moveSection:toSection:
这些通常在
的调用中使用- beginUpdates
- endUpdates
检查docs