iphone - 合并 CoreData 托管上下文时出现异常/崩溃

标签 iphone objective-c ios core-data ios5

我在尝试将托管上下文(在后台线程上运行)与我的主托管上下文(在主线程上)合并时遇到以下异常。我似乎无法在我自己的@try 表达式中捕捉到异常。有没有人对这个问题有任何见解?

我正在使用默认的合并策略,但我不确定这是正确的 - 这个问题是间歇性的 - 很少发生但会导致我的应用程序崩溃。

Exception Type:  EXC_CRASH (SIGABRT)
Exception Codes: 0x00000000, 0x00000000
Crashed Thread:  0

Last Exception Backtrace:
0   CoreFoundation                  0x37e3b8bf __exceptionPreprocess + 163
1   libobjc.A.dylib                 0x319211e5 objc_exception_throw + 33
2   CoreData                        0x344b7ea5 -[NSSQLiteStatement cachedSQLiteStatement] + 1
3   CoreData                        0x344b774f -[NSSQLiteConnection prepareSQLStatement:] + 55
4   CoreData                        0x3455b049 -[NSSQLChannel selectRowsWithCachedStatement:] +  61
5   CoreData                        0x34586d63 newFetchedRowsForFetchPlan_MT + 783
6   CoreData                        0x344bfb07 -[NSSQLCore newRowsForFetchPlan:] + 351
7   CoreData                        0x34565011 -[NSSQLCore fetchRowForObjectID:] + 1005
8   CoreData                        0x344d1a57 -[NSSQLCore newValuesForObjectWithID:withContext:error:] + 195
9   CoreData                        0x344d0f83 _PFFaultHandlerLookupRow + 423
10  CoreData                        0x3450e111 -[NSFaultHandler fulfillFault:withContext:] + 25
11  CoreData                        0x34518999 -[NSManagedObject(_NSInternalMethods) _newPropertiesForRetainedTypes:andCopiedTypes:preserveFaults:] + 77
12  CoreData                        0x345178ef -[NSManagedObject(_NSInternalMethods) _newAllPropertiesWithRelationshipFaultsIntact__] + 79
13  CoreData                        0x345284db -[NSManagedObjectContext(_NSInternalChangeProcessing) _establishEventSnapshotsForObject:] + 47
14  CoreData                        0x3452694b -[NSManagedObjectContext deleteObject:] + 155
15  CoreData                        0x345238a1 -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] + 813
16  CoreData                        0x34522c35 -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] + 189
17  myapp                       0x0008f0e9 0x8d000 + 8425
18  CoreFoundation                  0x37d9a22b -[NSObject performSelector:withObject:] + 43
19  Foundation                      0x31d75757 __NSThreadPerformPerform + 351
20  CoreFoundation                  0x37e0fb03 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
21  CoreFoundation                  0x37e0f2cf __CFRunLoopDoSources0 + 215
22  CoreFoundation                  0x37e0e075 __CFRunLoopRun + 653
23  CoreFoundation                  0x37d914dd CFRunLoopRunSpecific + 301
24  CoreFoundation                  0x37d913a5 CFRunLoopRunInMode + 105
25  GraphicsServices                0x3790ffcd GSEventRunModal + 157
26  UIKit                           0x35221743 UIApplicationMain + 1091

我在 nsoperation 的 start() 中初始化背景上下文,如下所示:

AppDelegate *appController = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[appController setPersistentStore:_managedObjectContext];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedDeletedObjects:) name:NSManagedObjectContextDidSaveNotification object:_managedObjectContext];

我还设置了一个通知事件,当在后台管理的上下文中删除对象时调用该事件,然后回调执行:

-(void)receivedDeletedObjects:(NSNotification *)note
{
    AppDelegate *appController = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext *mainContext = [self managedObjectContext];
[mainContext performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:note waitUntilDone:NO];

}

这就是代码。我有 4 个不同的后台线程,每个线程都有自己的托管上下文,以这种方式与主上下文合并做同样的事情。我想知道多个线程同时进入 mergeChangesFromContextDidSaveNotification 但不应该是这种情况,因为它总是在主线程上调用。

最佳答案

这个怎么样:

(全部在 AppDelegate 中,从后台线程调用 freshContextForBackgroundTask 并使用 save: 触发合并。)注意 syncObj 是一个普通的 NSObject 实例,当使用许多后台线程时(或者只是运气不好)调度)

-(NSManagedObjectContext*) freshContextForBackgroundTask {
    @synchronized(syncObj) {
        NSManagedObjectContext* r = [[NSManagedObjectContext alloc] init];
        [r setPersistentStoreCoordinator:self.managedObjectContext.persistentStoreCoordinator];
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(backgroundContextDidSave:)
                                                     name:NSManagedObjectContextDidSaveNotification
                                                   object:r];
        return r;
    }
}


- (void)backgroundContextDidSave:(NSNotification *)notification {
    /* Make sure we're on the main thread when updating the main context */
    //NSLog(@"merging change: %@",notification);
    dispatch_async(dispatch_get_main_queue(), ^{
        NSManagedObjectContext *context = [self managedObjectContext];
        // this for loop may not be needed for your purpose.
        for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
            [[context objectWithID:[object objectID]] willAccessValueForKey:nil];
        }
        [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];

    });
}

你的方法看起来很奇怪。尤其是当您将应用委托(delegate)的持久存储设置为 (nil) 新初始化的上下文之一时。

关于iphone - 合并 CoreData 托管上下文时出现异常/崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9234548/

相关文章:

ios - 是否可以在同一个 iOS 应用程序中同时支持 Facebook 登录和 Google Plus 登录?

iphone - 使用线程批量更新核心数据时出错

iphone - iOS 键盘显示 SAVE

iphone - 如何使用设备相机在 iphone 应用程序中以编程方式拍摄图片?

ios - 如何快速裁剪圆孔中的缩放图像

ios - 在指定时间间隔使用 CoreLocation 在后台检索 CoreMotion 数据

ios - iPhone 7 上未收到 GCM 推送

objective-c - @interface 括号内外声明的变量

c++ - iOS 从 openCV cv::Point 获取 CGPoint

iphone - 将 UITableViewController 转换为普通 UIViewController 的问题