【问题标题】:iOS 7 - CoreData Migration - Xcode 5iOS 7 - 核心数据迁移 - Xcode 5
【发布时间】:2013-11-26 10:22:11
【问题描述】:

我在执行 CoreData 迁移时遇到了一个非常奇怪的问题。

基本上,我有 2 个实体,在其中一个中添加一个属性,在另一个中,我将属性类型从 NSString 更改为 NSArray(Transformable)。 到目前为止,一切顺利,运行良好,经过测试,迁移后数据完整性完好。

如果我在 Xcode 5 上运行完全相同的代码会出现问题(我不知道它是否与 iOS SDK 7.0 或 Xcode 5 有关),但迁移会运行并损坏数据。

我最终创建了一个简单的项目来演示正在发生的事情。 https://dl.dropboxusercontent.com/u/1393279/CoreDataMigration.zip

重现的步骤是: - 在 Xcode 5 (iOS SDK 7.0) 上,你可以使用模拟器 -

1 - 打开项目“BeforeMigration”并执行。查看创建的日志和数据,目前没有问题;

2 - 停止项目;

3 - 打开项目“AfterMigration”,构建并运行。

4 - 查看迁移已执行,但数据已损坏:

2013-11-13 12:22:29.778 CoreDataMigration[7223:70b] CoreData:错误: fetchRowForObjectID 期间的异常:* -[NSKeyedUnarchiver initForReadingWithData:]: 无法理解的存档 (0x43, 0x32, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0) 用户信息为 (null) 2013-11-13 12:22:29.782 CoreDataMigration[7223:70b] 终止应用程序由于 未捕获的异常'NSInvalidArgumentException',原因:'** -[NSKeyedUnarchiver initForReadingWithData:]:无法理解的存档(0x43、0x32、0x0、0x0、0x0、0x0、0x0、0x0)'

AFAIK,无法理解的存档意味着 CoreData 上的数据损坏。

难以理解的是,相同的代码在以前也可以运行,因此,如果是逻辑问题,它应该发生在 Xcode 4.5 上。我查找了 CoreData Diffs,但没有找到任何相关内容。

如果有人知道可能是什么问题,我将不胜感激。 谢谢。

【问题讨论】:

  • 什么意思,你把一个属性改成了一个NSArray? Core Data 没有数组类型。你如何保存数据,如何将 NSString 迁移到 NSArray?
  • 对不起,我换成了可变形的
  • 我发现只有当我调用“backupSourceStoreAtURL”时才会出现问题。看来我不能重命名 .sqlite 文件了。不知道为什么。
  • backupSourceStoreAtURL 方法是什么?它不属于 Core Data 或 Apple 的任何 API。
  • 这是一种从我的原始存储创建备份的自定义方法。基本上,我从原始存储创建备份,然后删除旧的 .sqlite 文件并重命名新文件以使用与旧文件相同的名称,以防万一出现问题时恢复备份文件。似乎在以前的 SDK 版本上我可以重命名 .sqlite 文件没有任何问题,现在我不能。

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


【解决方案1】:

在 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

【讨论】:

    【解决方案2】:

    尝试使用 moGenerator link 并尝试以下步骤:

    • 使用 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 的最佳实践

    【讨论】:

      猜你喜欢
      • 2015-03-07
      • 2019-08-10
      • 1970-01-01
      • 1970-01-01
      • 2011-09-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多