2

I have an operation object which creates it's own Managed Object Context. The operation object performs calculation basically to take off load from main thread while main thread concentrates on the UI aspect. This operation object's MOC shares a common persistent store across the application.

It sometimes happens such that, while the operation is being performed, the MOC of main thread is notified of changes in backend. So, I try to merge the changes of MOC, where some of the deletions in model objects might happen. In some rare cases, as I observe, the operation object might not have been realized yet and they are in fault state and at the same time main thread stores the changes into MOC (and to persistent store). My app is crashing in such scenario.

As per the standard texts, I have a dedicated MOC for my threads and as per my understanding, the data for faults should be accessed from the MOC of the thread. Does it make a difference in accessing fault requests from MOC of the thread, when say, the same object might have been deleted from the store?

Please see this stack trace: enter image description here

What would be a better way of handling this?

I do understand from this post: https://stackoverflow.com/a/5722914/260665 that the managed object context of thread is not aware of the changes underlying the store and the faulted objects are expected to exist in the store. So, better it would be to either:

  1. Update the collection of objects in the thread when there are any underlying changes (deletion) in the store by using the NSManagedObjectContextDidSaveNotification notification (From: https://stackoverflow.com/a/5722914/260665)

  2. Check whether the NSManagedObject's record exists in the store before trying to access it's properties by using -existingObjectWithID on the MOC (From: https://stackoverflow.com/a/14297708/260665)

  3. Handle exceptions in code? (Last resort, from: https://stackoverflow.com/a/15361906/260665)

I cannot possibly go ahead with solutions 1 & 2 for it's not the NSManagedObject's properties directly am accessing, I have NSFetchedResultController which have sort descriptors inside which the app is crashing:

-(NSMutableArray*)fetchedTaskObjects
{
    if (nil==fetchedTaskObjects_ && self.taskLocalFetchedResultsController && self.persistantTaskFetchedResultsController)
    {
        NSArray *allNonPersistantTasks = [self.taskLocalFetchedResultsController fetchedObjects];
        NSArray *allPersistantTasks = [self.persistantTaskFetchedResultsController fetchedObjects];

        fetchedTaskObjects_ = [[NSMutableArray alloc] init];
        [fetchedTaskObjects_ addObjectsFromArray:allNonPersistantTasks];
        [fetchedTaskObjects_ addObjectsFromArray:allPersistantTasks];
        NSSortDescriptor *tasksSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.mockTaskCounter"
                                                                              ascending:YES];
        NSSortDescriptor *shortTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.shortText"
                                                                                  ascending:YES];
        NSSortDescriptor *headerTextSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"self.accountAssignmentText"
                                                                                   ascending:YES];
        [fetchedTaskObjects_ sortUsingDescriptors:[NSArray arrayWithObjects:tasksSortDescriptor, shortTextSortDescriptor, headerTextSortDescriptor, nil]];
    }
    return fetchedTaskObjects_;
}

So any suggestions of finding the solution in a right way?

Edit: The error (exception) which I am getting:

CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>'

Which line it crashes?

It crashes in any one of the sort descriptors where the internal property of the faluted Managed object is tried to access by the sort descriptors for sorting purpose. Since it is a thread, we are not sure when exactly the underlying object is deleted in the store. So, the thread crash sometimes also occurs in my statistics calculation code.

Why am combining the result of two FRC?

Because, the project initially started out with different MOCs for these 2 cases, now though the MOC is single the differentiation still remains. But I don't think it is a problem to have discrete FRCs with it's own purpose.

4

2 回答 2

1

如果你不能合并或者不想触碰操作MOC——比如因为它正在使用中,你需要保证操作数据更新变成序列化的。

这个想法是,当操作正在运行时,它假定其当前的数据状态视图是恒定的,因此不得更改。

您有几个选择来保证这一点:

如果操作正在运行,并且您收到更新请求并且想要立即更新包括共享持久存储在内的数据,您需要首先取消操作并等待操作完成(随后在操作的 MOC 上不会发生访问)。然后开始更新主 MOC 中的数据。当更新完成(包括持久存储)后,您可以使用新初始化正确合并的 MOC重新启动操作- 反映数据的实际状态。

同样,您可以将更新请求推迟到运行操作完成之后。

于 2013-10-23T11:31:57.313 回答
1

做了足够的研究,避免这种情况发生的唯一方法是通过收听通知(问题中提到的第一个解决方案)来更新集合,另一种方法是-existingObjectWithID在访问属性之前仔细检查(有问题的第二个解决方案)。

但就我而言,已删除(来自持久存储)托管对象的属性正在由排序描述符在内部访问。让我别无选择,只能处理线程中的异常(有问题的第三种解决方案)并忽略该线程的(错误)结果。

于 2013-10-03T07:33:28.913 回答