两天前我发布了应用程序。根据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:]
答案 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打印一些有用的信息。
您可能会发现这有助于调试您的问题。您可以将重复部分移动到一个带有两个字符串的函数中,即旧数据模型的文件名和最新的文件名。