应用更新后,核心数据轻量级迁移崩溃

时间:2012-03-20 16:19:24

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

两天前我发布了应用程序。根据AppStore的反馈和itunesconnect的崩溃报告,发布时会出现很多崩溃事件。但不是100%的用户遭受了损失,可能只有30%。

我已经阅读了崩溃日志并发现了一个问题。它正在崩溃数据库迁移过程。我使用数据库的轻量级迁移。 通常我会非常仔细地添加新的datamodel版本。甚至在每个版本之前我都安装了以前版本的App,使用它已经有一段时间了,然后才安装它上面的最新版本。那是这个时候。

我查看了两个数据模型(之前和现在)。添加:

1)新实体(轻量级迁移即可)
2)现有实体内的新字段。它们都是可选的。 (适用于轻量级迁移)
3)现有实体中的一个新字段,我将其作为可选和索引。 (好吗?)

没有重命名现有字段和实体。


我做错了什么?


堆栈追踪:

Thread 0 name:  Dispatch queue: com.apple.main-thread
Thread 0:
0   libsystem_kernel.dylib          0x352f439c pread + 20
1   libsqlite3.dylib                0x30d2d632 unixRead
2   libsqlite3.dylib                0x30d4221a readDbPage
3   libsqlite3.dylib                0x30d41156 sqlite3PagerAcquire
4   libsqlite3.dylib                0x30d583be moveToChild
5   libsqlite3.dylib                0x30d8e0e8 moveToLeftmost
6   libsqlite3.dylib                0x30d59582 sqlite3BtreeNext
7   libsqlite3.dylib                0x30d54328 sqlite3VdbeExec
8   libsqlite3.dylib                0x30d4f6c2 sqlite3_step
9   CoreData                        0x329e8e2e _execute
10  CoreData                        0x329e8d64 -[NSSQLiteConnection execute]
11  CoreData                        0x32a8bd54 -[NSSQLConnection prepareAndExecuteSQLStatement:]
12  CoreData                        0x32add63c -[_NSSQLiteStoreMigrator performMigration:]
13  CoreData                        0x32ad42b8 -[NSSQLiteInPlaceMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
14  CoreData                        0x32a79c02 -[NSMigrationManager migrateStoreFromURL:type:options:withMappingModel:toDestinationURL:destinationType:destinationOptions:error:]
15  CoreData                        0x32ac5bf4 -[NSStoreMigrationPolicy(InternalMethods) migrateStoreAtURL:toURL:storeType:options:withManager:error:]
16  CoreData                        0x32ac519c -[NSStoreMigrationPolicy migrateStoreAtURL:withManager:metadata:options:error:]
17  CoreData                        0x32ac6b58 -[NSStoreMigrationPolicy(InternalMethods) _gatherDataAndPerformMigration:]

2 个答案:

答案 0 :(得分:2)

这些用户是否有多次使用.xcversion?核心数据不会为您“链接”升级。因此,如果您有V1,V2和V3,并且V3成为当前版本,则V1中的任何人都将无法升级。可以添加自己的代码,帮助“逐步通过”V1到V2,然后V2到V3。我相信Marcus Zarra的“核心数据”一书的示例代码可以做到这一点。

答案 1 :(得分:1)

如果这是数据模型的V3,您还需要将V1和V2 xcdatamodel与随附的应用程序一起包含,以防部分用户仍在V1并且从未升级到V2。听起来你有一个V1数据模型,但没有包含它 - 但我不确定,你可能只是在谈论你已经完成这个的其他应用程序。

此外,您会注意到Xcode不管理有序的数据模型列表,您只能选择哪一个是当前的数据模型。它无法自动升级V1-> ...-> Vm-> Vn,因为它对旧版本之间的顺序一无所知,只是说它们需要成为Vn才能工作。尝试使用文本编辑器在xcdatamodeld包中进行搜索。

如果您完全依赖Core Data提供的行为,您的所有先前版本必须能够直接迁移到最新版本,无论是推断的映射模型,还是包括显式映射模型:来自V1 - > Vn,V2-> Vn,...,Vm-> Vn。这就是为什么有些人编写自己的代码来管理它。

我相信这正是斯科特在答案中所描述的。

在我们的应用程序开发过程中,我们创建了大约6个版本的数据模型(我们在将v1发送到App Store之前已经完成了最新的版本)。我发现编写单元测试非常有帮助,这些单元测试验证了Core Data 可以创建推断的映射模型,并且轻量级迁移可以正常工作。

要做到这一点:

NSURL *sourceURL = /* exercise for reader */, *destinationURL = /* exercise */;

NSManagedObjectModel *source = [[NSManagedObjectModel alloc] initWithContentsOfURL:sourceURL];
NSManagedObjectModel *destination = [[NSManagedObjectModel alloc] initWithContentsOfURL:sourceURL];

NSError *mappingError;
NSMappingModel *inferred = [NSMappingModel inferredMappingModelForSourceModel:source destinationModel:destination error:&mappingError];

在此代码块的末尾,您可以断言推断!= nil,如果它是nil,您可以通过检查mappingError打印一些有用的信息。

您可能会发现这有助于调试您的问题。您可以将重复部分移动到一个带有两个字符串的函数中,即旧数据模型的文件名和最新的文件名。