CoreData SIGABRT 同时保存主 MOC。为啥?

Posted

技术标签:

【中文标题】CoreData SIGABRT 同时保存主 MOC。为啥?【英文标题】:CoreData SIGABRT while saving main MOC. Why?CoreData SIGABRT 同时保存主 MOC。为什么? 【发布时间】:2014-05-03 16:05:28 【问题描述】:

我对保存主要 MOC 时遇到的崩溃感到非常困惑:

-(void) saveMainMOC

[_mainMOC performBlockAndWait:^
    NSError *errMain=nil;
    NSMutableArray *objs = [NSMutableArray array];
    for (NSManagedObject *obj in [[[_mainMOC insertedObjects] allObjects] arrayByAddingObjectsFromArray:[[_mainMOC updatedObjects] allObjects]]) 
        if (obj) 
            [objs addObject:obj];
        
    
    if (![_mainMOC obtainPermanentIDsForObjects:objs error:&errMain]) 
        NSLog(@"MainViewController::saveMainMOC.obPeID");
    

    if (![_mainMOC save:&errMain])  // THE SIGABRT OCCURS HERE
        NSLog(@"MainViewController::saveMainMOC.saveMain");
    
];

这是异常和堆栈跟踪:

2014-05-03 17:52:27.317 uRSS[4060:60b] *** Terminating app due to uncaught exception 'NSObjectInaccessibleException', reason: 'CoreData could not fulfill a fault for '0x9c31690 <x-coredata://9092A9F4-DAE0-4413-AADF-E137FBB3A860/Post/p1128>''
*** First throw call stack:
(
0   CoreFoundation                      0x028fd1e4 __exceptionPreprocess + 180
1   libobjc.A.dylib                     0x01faf8e5 objc_exception_throw + 44
2   CoreData                            0x01c80beb _PFFaultHandlerLookupRow + 2715
3   CoreData                            0x01c80147 -[NSFaultHandler fulfillFault:withContext:forIndex:] + 39
4   CoreData                            0x01c7fd23 _PF_FulfillDeferredFault + 259
5   CoreData                            0x01c8c0a9 _PF_Handler_WillAccess_Property + 57
6   CoreData                            0x01c8beda _PF_ManagedObject_WillChangeValueForKeyIndex + 74
7   CoreData                            0x01c8f4c7 _sharedIMPL_setvfk_core + 151
8   CoreData                            0x01cc0d06 -[NSManagedObject(_PFDynamicAccessorsAndPropertySupport) _setGenericValue:forKey:withIndex:flags:] + 54

saveMainMOC方法是从下面的saveLocalMOC方法调用的:

-(void)saveLocalMOC

[_localMOC performBlockAndWait:^
    NSError *errLoc=nil;

    NSMutableArray *objs = [NSMutableArray array];
    for (NSManagedObject *obj in [[[_localMOC insertedObjects] allObjects] arrayByAddingObjectsFromArray:[[_mainMOC updatedObjects] allObjects]]) 
        if (obj) 
            [objs addObject:obj];
        
    
    if (![_localMOC obtainPermanentIDsForObjects:objs error:&errLoc]) 
        NSLog(@"MainViewController::saveLocalMOC.obPeID");
    

    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc addObserver:self selector:@selector(_localMOCDidSave:)
               name:NSManagedObjectContextDidSaveNotification object:_localMOC];

    if (![_localMOC save:&errLoc]) 
        NSLog(@"MainViewController::saveLocalMOC.saveLocal");
    

    [nc removeObserver:self name:NSManagedObjectContextDidSaveNotification object:_localMOC];

    [self saveMainMOC];
];

注意:如果我从两个过程中删除 obtainPermanentIDsForObjects,它也会崩溃。

这里也是_localMOCDidSave观察者。

- (void)_localMOCDidSave:(NSNotification *)notification 
if (_mainMOC) 
    [_mainMOC performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:)
                                   withObject:notification waitUntilDone:YES];


我真的被这一切弄糊涂了,我做错了什么?

主 MOCS 和本地 MOCS 以这种方式初始化:

    _mainMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    [_mainMOC setParentContext:_saveMOC];
    [_mainMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];

self.localMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[self.localMOC setParentContext:self.mainMOC];
[self.localMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];

saveMOC 就是这样创建的:

        _saveMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [_saveMOC setPersistentStoreCoordinator:coordinator];

该错误通常出现在数百条帖子记录的初始加载期间。

【问题讨论】:

core data child/parent save exception的可能重复 【参考方案1】:

(部分)修复here:

我就是这样解决的:

    [_mocInMemoryForDynamicInformation.parentContext obtainPermanentIDsForObjects:@[session] error:&error];

【讨论】:

以上是关于CoreData SIGABRT 同时保存主 MOC。为啥?的主要内容,如果未能解决你的问题,请参考以下文章

保存期间CoreData比较错误

删除 CoreData 对象,然后调用 [tableView reloadData] 会导致 SIGABRT

反映 PS 中每个现有记录的 coredata-MO 修改

CoreData 在后台 MOC 的保存操作期间无法完成故障

SIGABRT - 针对解析推送通知

CoreData prepareForDeletion 调用无限次