使用 Core Data 异步 UISearchDisplayController 时出现 NSRangeException

发布于 2024-11-15 02:16:00 字数 1699 浏览 3 评论 0原文

我正在异步获取数据,并以此为指导: 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'

当访问匹配对象 ivar 来构造表单元格时,会抛出此错误:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

崩溃并不是一直发生,只是似乎随机发生。我猜测在某个地方,matchingObjects 数组的计数返回了某个值,该值发生了变化并且没有被更新。

我不完全确定如何处理这个问题 - 已经研究了几个小时了,有什么我遗漏的吗?

I'm asynchronously fetching data, and I've used this as a guide: http://deeperdesign.wordpress.com/2011/05/30/cancellable-asynchronous-searching-with-uisearchdisplaycontroller/

In

- (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];
}

Every now and then I'll get something to the effect of:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSArray objectAtIndex:]: index 0 beyond bounds for empty array'

This is thrown at the matchingObjects ivar when accessing it to construct the table cell in:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

The crash doesn't occur all the time, just seems to happen on random occasions. I'm guessing that somewhere the count on the matchingObjects array is returning a certain value, which changes and is not being updated.

I'm not entirely sure of how to deal with this - been looking over this for hours, is there something I'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

执妄 2024-11-22 02:16:00

我花了一段时间才弄清楚它是什么,但我再次查看了我刚刚链接的示例。我在后台线程中更新 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”的临时保存数组中,并且首先在主线程中更新matchingObjects iVar,然后重新加载tableView。这样,tableView 始终引用一个在访问时永远不会更改的数组,因为 tableView 依赖matchingObjects 来获取行数和数据。

I figured out what it was - took me a while, but I looked again at the example that I just linked. I was updating the self.matchingObjects iVar in the background thread, which on some occasions caused a mismatch between the range of the array available in the main thread and the background thread. So for example, the variable may have been updated in the background thread, and the main thread may still be accessing a part of the range that no longer exists in the variable since it was updated.

Fixed it by amending my code as follows:

 [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];
    }];

}];

Now the results of the search are loaded into a temporary holding array named "results", and the matchingObjects iVar is first updated in the main thread and then the tableView is reloaded. This way, the tableView always is referring to an array that is never changed whilst it is being accessed, since the tableView relies on matchingObjects to get the number of rows and data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文