我正在异步获取数据,我将其用作指南:http://deeperdesign.wordpress.com/2011/05/30/cancellable-asynchronous-searching-with-uisearchdisplaycontroller/
在
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
//setup request / predicate etc...
[self.searchQueue addOperationWithBlock:^{
NSError *error;
self.matchingObjects = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[self.searchDisplayController.searchResultsTableView reloadData];
}];
}];
// Return YES to cause the search result table view to be reloaded.
return NO;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
// Return the number of rows in the section.
return [self.matchingObjects count];
}
每隔一段时间我就会得到一些效果:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 0 beyond bounds for empty array'
当访问它以在以下位置构造表格单元格时,会在matchingObjects ivar处抛出此内容:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
崩溃不会一直发生,似乎只是偶然发生。我猜测,matchObjects数组上的count正在返回某个值,该值会更改并且不会更新。
我不完全确定如何处理这个问题 - 几个小时以来一直在研究这个问题,有什么我想念的吗?
答案 0 :(得分:1)
我想出它是什么 - 花了我一段时间,但我再次看了一下我刚刚联系的例子。我正在后台线程中更新self.matchingObjects iVar,这在某些情况下导致主线程中可用的数组范围与后台线程不匹配。因此,例如,变量可能已在后台线程中更新,并且主线程可能仍在访问变量中已不再存在的范围的一部分。
通过修改我的代码来修复它:
[self.searchQueue addOperationWithBlock:^
{
NSError *error;
NSArray *results = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
self.matchingObjects = results;
[self.searchDisplayController.searchResultsTableView reloadData];
}];
}];
现在搜索结果被加载到名为“results”的临时保存数组中,并且matchObjects iVar首先在主线程中更新,然后重新加载tableView。这样,tableView总是引用一个在访问时从不更改的数组,因为tableView依赖于matchesObjects来获取行数和数据。