4

I'm having a very curious problem performing a CoreData Migration.

Basically, I have 2 entities, where in one of them I add a property and in the other, I change a property type from NSString to NSArray(Transformable). So far, so good, it works well, tests were made and the data integrity was intact after the migration.

The problem happens if I run the exact same code on Xcode 5 (I don't know if it's related to iOS SDK 7.0 or Xcode 5), but the migration runs and corrupts the data.

I ended up creating a simple project to demonstrate what's happening. https://dl.dropboxusercontent.com/u/1393279/CoreDataMigration.zip

The steps to reproduce is: - On Xcode 5 (iOS SDK 7.0), you can use the simulator -

1 - Open the project "BeforeMigration" and execute. See the logs and data created, no problem so far;

2 - Stop the project;

3 - Open the project "AfterMigration", build and run.

4 - See that the migration is executed, but the data gets corrupted:

2013-11-13 12:22:29.778 CoreDataMigration[7223:70b] CoreData: error: exception during fetchRowForObjectID: * -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x43, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) with userInfo of (null) 2013-11-13 12:22:29.782 CoreDataMigration[7223:70b] Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '** -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x43, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0)'

AFAIK, incomprehensible archive means corrupted data on CoreData.

What's difficult to understand is that the same exact code worked before, so, if it's a logic problem, it should have happened on Xcode 4.5. I looked for CoreData Diffs but didn't find anything relevant.

If anyone have any idea of what could be the problem, I would appreciate. Thanks.

4

2 回答 2

3

在 iOS 7 中,Core Data SQLite 存储的默认日志模式已更改为 Write-Ahead Logging (WAL),以提高可靠性、性能和并发性。

问题是我没有使用核心数据移动 -wal 文件。解决它的一种方法是删除 -wal 使用:

NSDictionary *options = @{NSSQLitePragmasOption:@{@"journal_mode":@"DELETE"}};

或移动 -wal :

- (NSPersistentStore *)migratePersistentStore:(NSPersistentStore *)store toURL:(NSURL *)URL options:(NSDictionary *)options withType:(NSString *)storeType error:(NSError **)error
于 2013-12-26T16:44:57.430 回答
2

尝试使用 moGenerator链接并尝试以下步骤:

  • 使用 MOGen(或 MOGenerator)在每次构建时从模型中自动生成核心数据模型实体类(为此使用专用的预构建目标);
  • 创建新数据模型时始终启用模型版本控制;
  • 创建数据模型的新版本时:

    1. 添加新的数据模型版本——称之为“新版本”;将其核心数据模型标识符设置为下一个所需版本(如:1.1 或 2.0 等)。这是模型版本的逻辑开发者友好标识符——它不会强制 Core Data 以不同的方式对待这个版本,除非对其进行重大更改;

    2. 通过将其版本标识符附加到名称来重命名曾经是当前模型版本的版本。例如,如果“MyDataModel.xcdatamodel”的版本标识符设置为 1.1 - 将其重命名为“MyDataModel_1.1.xcdatamodel”;

    3. 将新添加的版本重命名为简单的模型名称,例如“MyDataModel.xcdatamodel”并将其设为当前版本。这样,您始终保持当前模型版本的名称相同,并且您的 MOGen 激活/构建脚本不会更改(如果您确实使用 MOGen - 您应该这样做);

    4. 根据需要修改当前模型;

    5. 根据对模型所做更改的规模,Core Data 轻量级迁移功能可以按原样处理它。如果更改范围很广,您可能需要定义自己的映射模型来帮助核心数据将旧数据存储迁移到模型的最新版本;

    6. 清洁您的产品;

    7. 重建您的产品;

    8. 测试它。

Andrey Kornich 的最佳实践

于 2013-12-04T17:49:01.930 回答