核心数据轻量级迁移 Xcode 崩溃

Posted

技术标签:

【中文标题】核心数据轻量级迁移 Xcode 崩溃【英文标题】:Core Data Lightweight Migration Xcode Crash 【发布时间】:2018-01-20 16:50:12 【问题描述】:

我正在尝试做一个涉及添加实体属性的非常简单的轻量级迁移。

在我的 AppDelegate 中有:

lazy var persistentContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "app")
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
        if let error = error as NSError? 
            fatalError("Unresolved error \(error), \(error.userInfo)")
        
    )
    return container
()

我尝试创建一个新的 .xcdatamodel 并在其中添加 Entity 属性,然后将 Model Version current 更改为这个新的数据模型。我也尝试过简单地将 Entity 属性添加到我现有的数据模型中。

在这两种情况下,当我点击运行时,Xcode 都会崩溃,我无法读取任何控制台输出,所以我不知道如何继续前进。 (我已经这样做了几十次了。)

我读过的所有内容似乎都表明,由于添加 Entity 属性是一个小改动,因此应该可以进行轻量级迁移,并且 shouldInferMappingAutomaticallyshouldMigrateStoreAutomatically 都应该默认为 true

如果使用addPersistentStore,有很多关于如何执行轻量级迁移的解释,但我没有使用它;我正在使用loadPersistentStores,看来我必须重构我的整个应用程序才能改变这一点(而且,无论如何,一切似乎都表明loadPersistentStores 是处理核心数据的新/批准的方式)。

更新

根据其他一些 SO 帖子,我已将延迟初始化更新为以下内容:

lazy var persistentContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "app")
    let url = NSPersistentContainer.defaultDirectoryURL()
    let description = NSPersistentStoreDescription(url: url)
    description.shouldAddStoreAsynchronously = true
    description.shouldInferMappingModelAutomatically = true
    description.shouldMigrateStoreAutomatically = true
    description.isReadOnly = false
    container.persistentStoreDescriptions = [description]
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
        if let error = error as NSError? 
            fatalError("Unresolved error \(error), \(error.userInfo)")
        
    )
    return container
()

我在if let error = error 处设置了一个断点,并且能够在 Xcode 崩溃之前捕获控制台。结果如下:

CoreData: warning:  View context accessed for persistent container app with no stores loaded
CoreData: warning:  View context accessed for persistent container app with no stores loaded
CoreData: error: -addPersistentStoreWithType:SQLite configuration:(null) URL:file:///var/mobile/Containers/Data/Application/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/Library/Application%20Support/ options:
NSAddStoreAsynchronouslyOption = 1;
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSReadOnlyPersistentStoreOption = 0;

... returned error Error Domain=NSCocoaErrorDomain Code=256 "The file couldn’t be opened." UserInfo=NSSQLiteErrorDomain=14, NSUnderlyingException=unable to open database file with userInfo dictionary 
NSSQLiteErrorDomain = 14;
NSUnderlyingException = "unable to open database file";

(lldb)

但现在我(再次)陷入困境。我无法想象为什么应用程序无法打开数据库文件并且不知道如何确定是什么阻止了它。

【问题讨论】:

【参考方案1】:

更新

我从延迟初始化中删除新代码并将其简单地返回:

lazy var persistentContainer: NSPersistentContainer = 
    let container = NSPersistentContainer(name: "bartender")
    container.loadPersistentStores(completionHandler:  (storeDescription, error) in
        if let error = error as NSError? 
            fatalError("Unresolved error \(error), \(error.userInfo)")
        
    )
    return container
()

我将断点放在同一个地方,这次在控制台中发现了这条消息:无法就地迁移存储:验证错误缺少强制目标属性上的属性值

这让我想到在我更新的实体的新属性中设置一个Default Value,现在 Xcode 不再崩溃,所以问题似乎已经解决了!

【讨论】:

以上是关于核心数据轻量级迁移 Xcode 崩溃的主要内容,如果未能解决你的问题,请参考以下文章

核心数据版本控制(轻量级迁移)问题

OS X 上的 Core Data 轻量迁移

迁移大型 Core Data 数据库崩溃

轻量级迁移核心数据

轻量级迁移后核心数据执行动作

iOS 核心数据轻量级迁移