NSFetchedResultsController 的 NSFetchedResultsChangeUpdate 事件中的 NSRangeException 异常 [英] NSRangeException exception in NSFetchedResultsChangeUpdate event of NSFetchedResultsController

查看:18
本文介绍了NSFetchedResultsController 的 NSFetchedResultsChangeUpdate 事件中的 NSRangeException 异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 UITableView,它使用 NSFetchedResultsController 作为数据源.

I have a UITableView that uses an NSFetchedResultsController as data source.

核心数据存储在多个并行运行的后台线程中更新(每个线程使用自己的NSManagedObjectContext).

The core data store is updated in multiple background threads running in parallel (each thread using it's own NSManagedObjectContext).

主线程观察NSManagedObjectContextDidSaveNotification通知并使用 mergeChangesFromContextDidSaveNotification: 更新它的上下文.

The main thread observes the NSManagedObjectContextDidSaveNotification notification and updates it's context with mergeChangesFromContextDidSaveNotification:.

有时NSFetchedResultsController 会发送一个NSFetchedResultsChangeUpdate 事件的 indexPath 不存在到那个时候就没有了.

Sometimes it happens that the NSFetchedResultsController sends an NSFetchedResultsChangeUpdate event with an indexPath that does not exist anymore at that point.

例如:fetched results controller的结果集包含1 个部分,包含 4 个对象.第一个对象在一个线程中被删除.最后一个对象在不同的​​线程中更新.然后有时发生以下情况:

For example: The result set of the fetched results controller contains 1 section with 4 objects. The first object is deleted in one thread. The last object is updated in a different thread. Then sometimes the following happens:

  • controllerWillChangeContent:被调用.
  • controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: 被调用类型 = NSFetchedResultsChangeDelete,indexPath.row = 0.
  • controller:didChangeObject:atIndexPath:forChangeType:newIndexPath: 被调用类型 = NSFetchedResultsChangeUpdate,indexPath.row = 3.

但是获取的结果控制器现在只包含 3 个对象,并且如果调用

But the fetched results controller contains only 3 objects now, and if call

MyManagedObject *obj = [controller objectAtIndexPath:indexPath]

根据NSFetchedResultsChangeUpdate更新table view cell事件,这会因 NSRangeException 异常而崩溃.

to update the table view cell according to the NSFetchedResultsChangeUpdate event, this crashes with a NSRangeException exception.

感谢您的任何帮助或想法!

Thank you for any help or ideas!

推荐答案

我现在找到了解决我的问题的方法.在更新事件的情况下,不需要调用

I have now found a solution for my problem. In the case of an update event, there is no need to call

[self.controller objectAtIndexPath:indexPath]

因为更新的对象已经作为 anObject 参数提供给 -controller:didChangedObject:... 委托.

because the updated object is already supplied as the anObject parameter to the -controller:didChangedObject:... delegate.

因此,我将 -configureCell:atIndexPath: 替换为直接使用更新对象的 -configureCell:withObject: 方法.这似乎没有问题.

I have therefore replaced -configureCell:atIndexPath: by a -configureCell:withObject: method that uses the updated object directly. This seems to work without problems.

代码现在看起来像这样:

The code looks now like this:

- (void)configureCell:(UITableViewCell *)cell withObject:(MyManagedObject *)myObj
{
    cell.textLabel.text = myObj.name;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCellIdentifier"];
    [self configureCell:cell withObject:[self.controller objectAtIndexPath:indexPath]];
    return cell;
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    UITableView *tableView = self.tableView;

    switch(type) {
    /* ... */           
    case NSFetchedResultsChangeUpdate:
        [self configureCell:[tableView cellForRowAtIndexPath:indexPath] withObject:anObject];
        break;
    /* ... */           
    }
}

这篇关于NSFetchedResultsController 的 NSFetchedResultsChangeUpdate 事件中的 NSRangeException 异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆