Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 独立ManagedObjectContext中的Coredata对象错误与持久存储中的更改_Iphone_Cocoa Touch_Cocoa_Core Data_Nsfetchedresultscontroller - Fatal编程技术网

Iphone 独立ManagedObjectContext中的Coredata对象错误与持久存储中的更改

Iphone 独立ManagedObjectContext中的Coredata对象错误与持久存储中的更改,iphone,cocoa-touch,cocoa,core-data,nsfetchedresultscontroller,Iphone,Cocoa Touch,Cocoa,Core Data,Nsfetchedresultscontroller,我有一个操作对象,它创建自己的托管对象上下文。操作对象执行计算基本上是为了从主线程上卸下负载,而主线程则专注于UI方面。此操作对象的MOC在整个应用程序中共享一个公共持久存储 有时,在执行操作时,主线程的MOC会收到后端更改的通知。因此,我尝试合并MOC的更改,其中可能会发生模型对象中的某些删除。在一些罕见的情况下,正如我观察到的,操作对象可能尚未实现,并且它们处于故障状态,同时主线程将更改存储到MOC(和持久存储)。我的应用程序在这种情况下崩溃了 根据标准文本,我的线程有一个专用的MOC,根据

我有一个操作对象,它创建自己的托管对象上下文。操作对象执行计算基本上是为了从主线程上卸下负载,而主线程则专注于UI方面。此操作对象的MOC在整个应用程序中共享一个公共持久存储

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

根据标准文本,我的线程有一个专用的MOC,根据我的理解,故障数据应该从线程的MOC访问。当同一个对象可能已从存储中删除时,从线程的MOC访问错误请求是否会有所不同

请查看此堆栈跟踪:

有什么更好的处理方法

我确实从这篇文章中了解到:thread的托管对象上下文不知道存储底层的更改,并且故障对象应该存在于存储中。因此,最好是:

  • 使用
    NSManagedObjectContextDidSaveNotification
    通知(发件人:)在存储中有任何基础更改(删除)时更新线程中的对象集合

  • 在尝试使用MOC上的
    -existingObjectWithID
    访问其属性之前,请检查存储区中是否存在
    NSManagedObject
    的记录(发件人:)

  • 处理代码中的异常?(最后手段,从:)

  • 我无法继续使用解决方案1和2,因为我访问的不是NSManagedObject的属性,我有NSFetchedResultController,其中包含排序描述符,应用程序正在崩溃:

    -(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_;
    }
    
    那么,有没有以正确的方式找到解决方案的建议

    编辑: 我得到的错误(异常):

    CoreData could not fulfill a fault for '0x2b0298a0 <x-coredata://E7E91AFC-5BE6-4996-B28F-92CD115A5D0A/CSTaskRegister/p14746>'
    
    CoreData无法实现“0x2b0298a0”的故障
    
    哪条线坏了

    它在任何一个排序描述符中崩溃,其中排序描述符尝试访问失效托管对象的内部属性以进行排序。因为它是一个线程,所以我们不确定到底什么时候在存储中删除了底层对象。因此,线程崩溃有时也发生在我的统计计算代码中

    为什么我要合并两个FRC的结果


    因为,该项目最初在这两种情况下使用不同的MOC,现在虽然MOC是单一的,但差异仍然存在。但是我不认为有独立的FRC是一个问题,因为它有自己的用途。

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


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

    如果无法合并或不想接触操作MOC(例如,因为它当前正在使用),则需要确保操作和数据更新序列化

    其思想是,当操作运行时,它假定其当前的数据状态视图是恒定的,因此不能更改

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

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


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

    您的应用程序在哪一行的
    获取的taskobjects
    上崩溃了?错误是什么?为什么要将两个
    NSFetchedResultsController
    获取的对象合并到一起?更新了问题并回答了您的问题。但是,我最终选择了使用异常处理的第三种解决方案,而忽略了此类操作的结果。值得一提的是,这是一个很好的建议。我可以推迟主MOC中的更新请求,或者取消操作并等待它们完成。请您添加关于为什么cocoa和应用程序中不首选异常处理的参考是否应该在例外情况下退出此答案,以便将来为其他人提供良好的参考?