Coredata 迁移崩溃

Posted

技术标签:

【中文标题】Coredata 迁移崩溃【英文标题】:Coredata Migration Crash 【发布时间】:2017-08-22 19:54:46 【问题描述】:

在我最新的应用更新中,有一些用户抱怨崩溃,我设法获得了崩溃报告。这是符号化崩溃日志中的崩溃原因。

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Triggered by Thread:  0

当我打电话给[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]时会发生这种情况

这是完整的堆栈跟踪:

Thread 0 name:  Dispatch queue: SQLQueue 0x12fecca10 for .database.db.migrationdestination_41b5a6b5c6e848c462a8480cd24caef3
Thread 0 Crashed:
0   libsystem_kernel.dylib          0x0000000180640164 __fcntl + 8
1   libsystem_kernel.dylib          0x0000000180625660 fcntl + 84
2   libsqlite3.dylib                0x0000000181ba3f90 0x181b3d000 + 421776
3   libsqlite3.dylib                0x0000000181bb9e50 0x181b3d000 + 511568
4   libsqlite3.dylib                0x0000000181bcdf34 0x181b3d000 + 593716
5   libsqlite3.dylib                0x0000000181bcdd98 sqlite3_wal_checkpoint_v2 + 492
6   libsqlite3.dylib                0x0000000181ba41b0 0x181b3d000 + 422320
7   libsqlite3.dylib                0x0000000181b7b288 sqlite3_step + 976
8   CoreData                        0x000000018391b194 _execute + 164
9   CoreData                        0x000000018394ffd8 -[NSSQLiteConnection commitTransaction] + 312
10  CoreData                        0x0000000183a6ced8 __43-[_NSSQLiteStoreMigrator performMigration:]_block_invoke + 2784
11  CoreData                        0x0000000183a36cbc __37-[NSSQLiteConnection performAndWait:]_block_invoke + 40
12  libdispatch.dylib               0x00000001804fe9a0 _dispatch_client_callout + 16
13  libdispatch.dylib               0x000000018050bee0 _dispatch_barrier_sync_f_invoke + 84
14  CoreData                        0x0000000183a36c08 -[NSSQLiteConnection performAndWait:] + 144
15  CoreData                        0x0000000183a6c35c -[_NSSQLiteStoreMigrator performMigration:] + 184
16  CoreData                        0x0000000183a63db0 -[NSSQLiteInPlaceMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:] + 1912
17  CoreData                        0x00000001839ee814 -[NSMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:] + 556
18  CoreData                        0x0000000183a5f090 -[NSStoreMigrationPolicy(InternalMethods) migrateStoreAtURL:toURL:storeType:options:withManager:error:] + 324
19  CoreData                        0x0000000183a5e3ec -[NSStoreMigrationPolicy migrateStoreAtURL:withManager:metadata:options:error:] + 120
20  CoreData                        0x0000000183a5fb08 -[NSStoreMigrationPolicy(InternalMethods) _gatherDataAndPerformMigration:] + 2440
21  CoreData                        0x00000001839fc188 __91-[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:]_block_invoke + 4160
22  CoreData                        0x0000000183a08630 gutsOfBlockToNSPersistentStoreCoordinatorPerform + 168
23  libdispatch.dylib               0x00000001804fe9a0 _dispatch_client_callout + 16
24  libdispatch.dylib               0x000000018050bee0 _dispatch_barrier_sync_f_invoke + 84
25  CoreData                        0x00000001839f7d70 _perform + 200
26  CoreData                        0x000000018390d5e4 -[NSPersistentStoreCoordinator addPersistentStoreWithType:configuration:URL:options:error:] + 388

我没有关于崩溃的更多详细信息。只有少数用户而不是所有用户都会发生这种情况。我不知道如何重现它以进行适当的修复。用户报告该应用程序已启动,被“冻结”了一段时间,然后崩溃了。而且它一直在这样做。

自从我发布应用程序以来,我查看了核心数据模型的最新版本,这个文件仍然完全相同。在开发过程中,我在中间添加了 5 个以上版本,但这应该不是问题吧?更新前应用内发布的版本保持不变...

编辑:我对模型所做的更改只是在现有实体上添加了一些新属性。但是,如果自动迁移失败,那么每个人都会失败,对吧?不只是少数用户?!?

所以我希望这里的某个人可能已经遇到了同样的问题以及如何解决它的解决方案。或者至少是一种如何在应用程序不崩溃的情况下检测问题的方法。然后我可以为这些用户重新创建数据库...

【问题讨论】:

这是一个有趣的堆栈跟踪。 Core Data 开始迁移,但在某个时候崩溃了。我会询问用户他们的设备是否空间不足。此外,编辑您的问题以描述您对模型所做的更改可能会很有用。 嘿汤姆,我会问用户!是什么让你认为它可能是低磁盘空间?我更新了关于更改的问题...我对模型所做的更改只是在现有实体上添加了一些新属性。但是,如果自动迁移失败,那么每个人都会失败,对吧?不只是少数用户?!?您对我如何重现该错误有任何想法吗? 由于它适用于大多数用户,看来您已正确设置迁移。您的堆栈跟踪支持这一点 - 一切都在运行,但随后 boom。这就留下了这些少数用户的独特之处的问题。空间不足不会影响大多数用户,并且可能会在原本正常的迁移过程中搞砸。 我刚刚看到在我的 iPhone 7 上进行迁移大约需要 1.5 秒。当设备速度较慢以致需要太长时间并且跳板因此关闭我的应用程序时,这可能是一个问题吗? 【参考方案1】:

核心数据迁移可能需要一些时间。如果您的第一个视图加载时间过长,那么看门狗将杀死您的应用程序。当您的用户拥有比您预期更多的数据时,可能会发生这种情况。而是添加一个迁移检查器。如果您需要进行迁移,请在加载商店时显示带有加载动画的加载 UI。

-(BOOL) storeNeedsMigrationAtURL:(NSString*) sourceStorePath
    if (![[NSFileManager defaultManager] fileExistsAtPath:sourceStorePath]) 
        // Database doesn't yet exist. No need to test data compatibility"
        return NO;
    
    NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:"<Your models directory name>" ];
    NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];

    NSError *error = nil;
    NSURL *sourceStoreURL = [NSURL fileURLWithPath:sourceStorePath];
    NSDictionary *sourceStoreMetadata = [NSPersistentStoreCoordinator metadataForPersistentStoreOfType:NSSQLiteStoreType URL:sourceStoreURL options:nil error:&error];

    // Do error checking... Removed from the code sample.
    NSManagedObjectModel *destinationModel = [psc managedObjectModel];
    BOOL isCompatible = [destinationModel isConfiguration:nil
                              compatibleWithStoreMetadata:sourceStoreMetadata];

    return isCompatible;

约 55 分钟见 https://vimeo.com/89370886 你也可以阅读 https://hamishrickerby.com/2012/06/04/core-data-migrations-and-large-data-sets/

【讨论】:

是的......确实......同时我做了类似的东西!但是isConfiguration:compatibleWithStoreMetadata 没有正确检测到它......相反,我现在正在检查实体哈希......如果我检测到需要迁移,然后我会向用户显示一个等待对话框并在后台迁移...... .以及为什么它只影响少数用户的问题是如果数据库不是那么满的话它很快,但是一旦用户有很多数据,它需要更长的时间......

以上是关于Coredata 迁移崩溃的主要内容,如果未能解决你的问题,请参考以下文章

属性名称更改期间的 CoreData 迁移问题

CoreData 模型更新崩溃

Coredata 手动迁移

在 CoreData 中迁移实体父级

iOS CoreData 版本升级和数据库迁移

Core Data 的推断映射模型创建(轻量级迁移)崩溃。线程问题?