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运行时,应用程序中的任何其他内容都不可能访问持久存储)只要看一眼代码,就可以知道您正在共享托管对象上下文?至少,创建托管对象上下文的地方只有一个,将来每次调用都会返回该引用?