Bryan Irace
Bryan Irace

Reputation: 1875

Core Data: Timeout adding persistent store on application launch

I have an app that creates a persistent store in application:didFinishLaunchingWithOptions. Adding the store can apparently take too long, which causes iOS to terminate the app before it finishes launching. The stack traces at the time of timing out looks like this. Does anyone know how to prevent this from happening?

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:]

Upvotes: 0

Views: 1745

Answers (2)

Marcus S. Zarra
Marcus S. Zarra

Reputation: 46728

badfood is a common launch crash. You need to get the creation of the Core Data stack off the main thread. I have discussed this a few times on here and other places in the past.

You can also look at Aplle's iCloud Core Datavidros as that launch code will solve your problem as well.

Keep in mind that your app will need to be able to launch without the stack being in place. For existing apps this can be a major change.

Update 2

This has always been recommended but unfortunately only recently has it been starting to show in the templates.

There are several things that can cause the adding of the persistent store to take longer:

  1. If you are migrating your database from one version to another; the migration occurs when you add the store to the coordinator.
  2. If you are adding iCloud to your application it will take significantly longer on the first launch.
  3. If Core Data determines that something needs to be done to the database for maintenance, it can take longer than expected.

The "right" answer is to add the store to the coordinator off the main thread.

The quick/bandaid answer would be to turn on sql logging for core data and then see what is going on during launch. Once you understand what is causing the delay you may be able to address it. If it is a migration then the right answer is probably the only answer.

Update 3

  1. Profile this in instruments. That will tell you where the slowness is.
  2. What does dataToMigrate = [self fetchSomeDataFromDatabase]; do?

Look at your time profile and that will tell you what is slow. Send me the time profile from instruments and I will look at it as well.

Upvotes: 4

Daij-Djan
Daij-Djan

Reputation: 50129

code is easy:

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

but as marcus said, make sure your app can handle not having CoreData ready at launch (it is async now) .. you could e.g. set A splash screen!? / a basic menu that doesnt use the db

Upvotes: 0

Related Questions