Coredata对象在独立ManagedObjectContext中的故障vs持久存储中的更改 [英] Coredata object fault in independent ManagedObjectContext vs changes in persistent store

查看:160
本文介绍了Coredata对象在独立ManagedObjectContext中的故障vs持久存储中的更改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个操作对象创建它自己的管理对象上下文。操作对象执行计算基本上是在主线程集中在UI方面时从主线程取出负载。这个操作对象的MOC在应用程序之间共享一个公共持久性存储。



有时会发生这样的情况,即在执行操作时,主线程的MOC被通知变化在后端。所以,我尝试合并MOC的更改,其中一些模型对象中的删除可能发生。在一些罕见的情况下,如我所观察到的,操作对象可能还没有实现,并且它们处于故障状态,同时主线程将改变存储到MOC(和持久存储)中。我的应用程序在这种情况下崩溃。



根据标准文本,我有一个专门的MOC为我的线程,根据我的理解,数据的故障应访问从线程的MOC。如果同一个对象可能已经从存储中删除,那么它是否会从线程的MOC访问故障请求?



请看这个堆栈跟踪:



什么



我从这篇文章中理解: http://stackoverflow.com/a/5722914/260665 线程的受管对象上下文不知道存储底层的更改,并且故障对象应该存在于存储中。所以,最好是:


  1. 更新线程中的对象集合, )通过使用 NSManagedObjectContextDidSaveNotification 通知(来自: http:// stackoverflow .com / a / 5722914/260665


  2. 检查 NSManagedObject 记录存在于商店中,然后尝试使用 -existingObjectWithID 在MOC上访问它的属性(从:http://stackoverflow.com/a/14297708/260665


  3. 在代码中处理异常? (最后手段,从: http://stackoverflow.com/a/15361906/260665


我不可能继续解决方案1& 2因为它不是NSManagedObject的属性直接访问,我有NSFetchedResultController其中有应用程序崩溃的排序描述符:

  (NSMutableArray *)fetchedTaskObjects 
{
if(nil == fetchedTaskObjects_&& self.taskLocalFetchedResultsController&& self.persistantTaskFetchedResultsController)
{
NSArray * allNonPersistantTasks = .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_;
}

有什么建议以正确的方式找到解决方案?



编辑:
我得到的错误(例外):

  CoreData无法为'0x2b0298a0< x-coredata:// E7E91AFC-5BE6-4996-B28F-92CD115A5D0A / CSTaskRegister / p14746>'



它崩溃了哪一行?



它在任何一个排序描述符中崩溃, faluted Managed对象的内部属性试图通过排序描述符进行访问以进行排序。由于它是一个线程,我们不确定底层对象何时在商店中被删除。因此,线程崩溃有时也会出现在我的统计计算代码中。



为什么要结合两个FRC的结果?



因为,该项目最初开始使用不同的MOCs为这2种情况,现在虽然MOC是单一的分化仍然存在。但我不认为这是有问题的离散FRCs与它自己的目的。

解决方案

避免这种情况的方法是通过监听通知(问题中提到的第一个解决方案)更新收集,另一种方法是用 -existingObjectWithID (第二个解决方案



但是在我的例子中,被删除的(从持久存储)被管理对象的属性正在被排序描述符内部访问。让我别无选择,只能处理线程中的异常(第三个解决方案),并忽略这个线程的(错误的)结果。


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:

What would be a better way of handling this?

I do understand from this post: http://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: http://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: http://stackoverflow.com/a/14297708/260665)

  3. Handle exceptions in code? (Last resort, from: http://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.

解决方案

Did enough research, the only way to avoid this happening is to update the collection by listening to the notifications (1st solution mentioned in the question) and another approach is to double check with -existingObjectWithID (2nd solution in question) before accessing the properties.

But in my case, the properties of deleted (from persistent store) Managed Objects are being accessed internally by the sort descriptors. Leaves me no choice but to handle the exception (3rd solution in question) in the thread and neglect the (erroneous) results of this thread.

这篇关于Coredata对象在独立ManagedObjectContext中的故障vs持久存储中的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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