【问题标题】:Core-Data migration on background thread failing when running as a UIBackgroundTask作为 UIBackgroundTask 运行时,后台线程上的核心数据迁移失败
【发布时间】:2012-01-25 12:05:58
【问题描述】:

我的代码:

    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 = "Fatal error. The database at /var/mobile/Applications/55B83D5F-CCF5-438E-BECA-B97DB5505541/Documents/Blah.sqlite is corrupted. SQLite error code:11, 'database disk image is malformed'";

仅当以下全部为真时才会发生迁移错误: * 迁移在后台线程上 * 迁移作为 UIBackgroundTask 运行 * 我在设备上运行,不是模拟器

我正在运行 iOS 4.3.5,为 iOS 4.0 构建。

【问题讨论】:

  • 哎呀...想通了。永远不要从主线程以外的任何地方调用 UIKit 中的任何东西。在这种情况下,我正在启动一个后台任务 ([[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:]),从而从后台线程向我的 UIApplication 实例发送消息。这是
  • __block UIBackgroundTaskIdentifier bgTask; 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 在文档中被特别标记为线程安全。你可能只是在掩盖真正的问题。
  • 你说得对,上面的代码实际上是行不通的(我有点草率了)。

标签: objective-c ios core-data ios4 core-data-migration


【解决方案1】:

没有看到migrateCoreDataStuff 的内容,很难看出确切的问题。然而,非主线程上的 Core Data 是一个棘手的问题。阅读http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html。您可能至少需要为新线程提供一个单独的托管对象上下文。

【讨论】:

  • 是的,那个方法很大,我不能在这里发布,但本质上它是从media.pragprog.com/titles/mzcd/code/ProgressiveMigration/… 逐步迁移的(我按照你的建议使用了一个单独的上下文,当 migrateCoreDataStuff 正在运行时,什么都没有应用程序中的 else 可能正在访问持久存储)
  • 简单看一下代码表明您正在共享托管对象上下文?至少,它只在一个地方被创建,并且将来每次调用都会返回该引用?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 2013-03-20
  • 1970-01-01
  • 1970-01-01
  • 2012-12-12
  • 1970-01-01
  • 2012-11-14
相关资源
最近更新 更多