我异步获取数据,并且已将其用作指南: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
崩溃并不会一直发生,只是偶然发生。我猜在matchingObjects数组上的计数返回某个值,该值会更改并且不会被更新。
我不太确定该如何处理-经过数小时的检查,我是否缺少某些东西?
最佳答案
我弄清楚是什么-花了我一段时间,但我再次看了一下刚才链接的示例。我在后台线程中更新了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依赖matchingObjects来获取行数和数据数。