【问题标题】:Core Data: Timeout adding persistent store on application launch核心数据:在应用程序启动时添加持久存储超时
【发布时间】:2012-11-11 16:54:40
【问题描述】:

我有一个在application:didFinishLaunchingWithOptions 中创建持久存储的应用程序。添加商店显然需要很长时间,这会导致 iOS 在应用程序完成启动之前终止应用程序。超时时的堆栈跟踪如下所示。有谁知道如何防止这种情况发生?

Exception Type:  00000020
Exception Codes: 0x000000008badf00d
Highlighted Thread:  0

Application Specific Information:
com.foo.bar failed to launch in time

Elapsed total CPU time (seconds): 23.490 (user 23.490, system 0.000), 78% CPU 
Elapsed application CPU time (seconds): 8.406, 28% CPU

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x31b8939c pread + 20
1   libsqlite3.dylib                0x31ed95d0 unixRead
2   libsqlite3.dylib                0x31eec106 readDbPage
3   libsqlite3.dylib                0x31eeb2a2 sqlite3PagerAcquire
4   libsqlite3.dylib                0x31f04096 moveToChild
5   libsqlite3.dylib                0x31f052c6 sqlite3BtreeNext
6   libsqlite3.dylib                0x31f01490 sqlite3VdbeExec
7   libsqlite3.dylib                0x31efa48a sqlite3_step
8   CoreData                        0x364f8892 _execute
9   CoreData                        0x364f878c -[NSSQLiteConnection execute]
10  CoreData                        0x3658bd94 -[NSSQLConnection prepareAndExecuteSQLStatement:]
11  CoreData                        0x365dd4f2 -[_NSSQLiteStoreMigrator performMigration:]
12  CoreData                        0x365d70dc -[NSSQLiteInPlaceMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
13  CoreData                        0x36577428 -[NSMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
14  CoreData                        0x365c8670 -[NSStoreMigrationPolicy(InternalMethods) migrateStoreAtURL:toURL:storeType:options:withManager:error:]
15  CoreData                        0x365c79c4 -[NSStoreMigrationPolicy migrateStoreAtURL:withManager:metadata:options:error:]
16  CoreData                        0x365c8ece -[NSStoreMigrationPolicy(InternalMethods) _gatherDataAndPerformMigration:]
17  CoreData                        0x364ec3b0 -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]

【问题讨论】:

    标签: ios core-data


    【解决方案1】:

    badfood 是一种常见的启动崩溃。您需要在主线程之外创建 Core Data 堆栈。过去我在这里和其他地方已经讨论过几次了。

    您还可以查看 Aplle 的 iCloud Core Datavidros,因为该启动代码也可以解决您的问题。

    请记住,您的应用需要能够在堆栈没有到位的情况下启动。对于现有的应用程序,这可能是一个重大变化。

    更新 2

    一直推荐使用此功能,但遗憾的是直到最近才开始在模板中显示。

    有几件事会导致添加持久性存储需要更长的时间:

    1. 如果您要将数据库从一个版本迁移到另一个版本;当您将商店添加到协调器时会发生迁移。
    2. 如果您将 iCloud 添加到您的应用程序中,第一次启动时将需要显着更长的时间。
    3. 如果 Core Data 确定需要对数据库执行某些操作以进行维护,则可能需要比预期更长的时间。

    “正确”的答案是将商店添加到主线程之外的协调器。

    快速/创可贴的答案是为核心数据打开 sql 日志记录,然后查看启动期间发生的情况。一旦您了解导致延迟的原因,您就可以解决它。如果是迁移,那么正确的答案可能是唯一的答案。

    更新 3

    1. 在仪器中对此进行分析。这会告诉你慢在哪里。
    2. dataToMigrate = [self fetchSomeDataFromDatabase]; 有什么作用?

    查看您的时间档案,这将告诉您什么是慢。把仪器的时间曲线发给我,我也会看的。

    【讨论】:

    • 有趣。我不认为这是必要的,因为当您创建一个新的 Xcode 项目时,生成的模板确实会在主线程上添加持久存储?这是我们看到的一个新问题,我不确定发生了什么变化。除了重写整个应用程序以依赖于可用的商店之外,还有其他侵入性较小的方法来缓解这种启动崩溃吗?
    • 非常感谢 - 这真的很有帮助。我仍然对究竟是什么导致这种情况发生感到困惑。我没有迁移数据库或使用 iCloud,我只是删除数据库(如果存在)然后创建一个新数据库。代码如下所示:notepad.cc/hiaxaiho16
    • 谢谢马库斯!我将尝试分析,但不确定我会有多少运气,因为我真的无法重现这个问题。 dataToMigrate = [self fetchSomeDataFromDatabase];只是简单地获取一些用户数据,以防止用户在设置新商店后必须重新登录。我想知道当我实际上尝试执行迁移时,问题是否可能是设置NSMigratePersistentStoresAutomaticallyOptionNSInferMappingModelAutomaticallyOption
    • 分析显示,从一个 MOM 迁移到另一个 MOM 需要很长时间。我不确定为什么,因为这是一次“轻量级”迁移。我正在考虑两种不同的方法:1)保留迁移但将其移至后台线程。这让我有点担心,因为它不应该花这么长时间,而且我们不需要迁移,只需要从旧存储中提取一些数据。 2) 将堆栈创建移动到后台线程,但也可以通过传递 NSIgnorePersistentStoreVersioningOption : @YES 来避免迁移,并且只手动迁移我知道可以从旧 MOM 获得的内容。
    【解决方案2】:

    代码很简单:

        dispatch_async(DISPATCH_QUEUE_PRIORITY_HIGH, ^{
            [self setupCoreDataStack]; //TODO
        })
    

    但正如马库斯所说,确保您的应用程序可以处理在启动时未准备好 CoreData(它现在是异步的).. 您可以例如设置启动画面!? / 一个不使用 db 的基本菜单

    【讨论】:

    • 我不会推荐这个。如果您在后台创建整个 堆栈,那么您的NSManagedObjectContext 将在从其下方消失的线程上创建。这会造成不好的情况,因为NSManagedObjectContext 是线程敏感的。我的建议是立即创建 MOM、PSC 和 MOC。然后将一个块拆分到队列中,以将存储添加到 PSC 异步。由于 MOC 就在那里,只是空的,因此创建 UI 变得更加容易。
    • 听起来不错的建议 :)) 但是....我不能也使用 __block 变量创建它吗?妈妈和 PSC .. 不是 moc
    • 或 [self setupStoreWithCompletionBlock],然后我将 MOM、PST 和 MOC 传回......从外面看起来不错!在里面我做异步的东西
    • 这使得它变得比它需要的更难。 1.创造妈妈; 2.创建psc; 3.创建moc。这些都应该是创建它们的任何类中的属性。 4.在后台队列上创建块; block 现在可以调用 [self psc] 来获取 psc 并向其添加商店。 5. 在主队列上调用类似[self stackInitialized]的块的结尾,并且Bob是你的叔叔。
    • :) 好的,下次我会这样做:D
    猜你喜欢
    • 2011-01-16
    • 1970-01-01
    • 2012-12-15
    • 1970-01-01
    • 2011-12-22
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-22
    相关资源
    最近更新 更多