Objective c 作为UIBackgroundTask运行时,后台线程上的核心数据迁移失败
我的代码:Objective c 作为UIBackgroundTask运行时,后台线程上的核心数据迁移失败,objective-c,ios,core-data,ios4,core-data-migration,Objective C,Ios,Core Data,Ios4,Core Data Migration,我的代码: dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ @autoreleasepool { // Now on a background thread // Setup background task __block UIBackgroundTaskIdentif
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
@autoreleasepool {
// Now on a background thread
// Setup background task
__block UIBackgroundTaskIdentifier bgTask;
void (^finishBackgroundTask)(void) = ^(void) {
[[UIApplication sharedApplication] endBackgroundTask:bgTask];
bgTask = UIBackgroundTaskInvalid;
};
// Start background task
bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:finishBackgroundTask];
// The method below migrates a core data database and takes ages
[MyClass migrateCoreDataStuff];
finishBackgroundTask();
}
});
我得到的错误是NSUnderlyingException=“致命错误。位于/var/mobile/Applications/55B83D5F-CCF5-438E-BECA-B97DB5505541/Documents/Blah.sqlite的数据库已损坏。sqlite错误代码:11,‘数据库磁盘映像格式不正确’代码>
只有在以下情况均为真时,才会发生迁移错误:
*迁移是在后台线程上进行的
*迁移正在作为UIBackgroundTask运行
*我在设备上运行,不是模拟器
我正在运行iOS 4.3.5,它是为iOS 4.0构建的。如果没有看到migrateCoreDataStuff
的内容,就很难看到确切的问题。然而,非主线程上的核心数据是一个棘手的问题。读一读。您可能至少需要为新线程提供一个单独的托管对象上下文。Whoops…解决了。除了主线程外,任何人都不应该调用UIKit中的anthing。在本例中,我正在启动一个后台任务([[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:][/code>),从而从后台线程发送UIApplication实例消息。这是错误的;void(^finishBackgroundTask)(void)=^(void){[[UIApplication sharedApplication]endBackgroundTask:bgTask];bgTask=UIBackgroundTaskInvalid;};bgTask=[[UIApplication sharedApplication]beginBackgroundTaskWithExpirationHandler:finishBackgroundTask];dispatch_async(dispatch_get_global_queue(dispatch_queue_PRIORITY_HIGH,0),^{@autoreleasepool{[MyClass migrateCoreDataStuff];dispatch_async(dispatch_get_main_queue(),finishBackgroundTask);});这不太可能是根本问题beginBackgroundTaskWithExpirationHandler
在文档中特别标记为线程安全。你可能只是掩盖了真正的问题。你是对的,上面的代码实际上不起作用(我有点仓促)。是的,这个方法很大,我不能在这里发布,但本质上是从(我按照您的建议使用一个单独的上下文,当migrateCoreDataStuff运行时,应用程序中的任何其他内容都不可能访问持久存储)只要看一眼代码,就可以知道您正在共享托管对象上下文?至少,创建托管对象上下文的地方只有一个,将来每次调用都会返回该引用?