简体   繁体   English

更改项目名称后Xcode 8 Core Data App崩溃

[英]Xcode 8 Core Data App Crash After Change of Project Name

I changed the name of my Xcode 8 project how described in this post How do I completely rename an Xcode project (ie inclusive of folders)? 我更改了Xcode 8项目的名称,如本文中所述。 如何完全重命名Xcode项目(即包含文件夹)?

Now when running the new version of the app on a device where the old version is installed the app crashes with the following error message: 现在,在安装了旧版本的设备上运行新版本的应用程序时,该应用程序崩溃并显示以下错误消息:

[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (OLD_PROJECTNAME.SomeObject) for key (NS.objects); [NSKeyedUnarchiver encodeObjectForKey:]:无法为密钥(NS.objects)解码类(OLD_PROJECTNAME.SomeObject)的对象; the class may be defined in source code or a library that is not linked 该类可以在源代码或未链接的库中定义

So it seems that the old name doesn't fit to the core data stack of the renamed version. 因此,似乎旧名称不适合重命名版本的核心数据堆栈。 How can I change this name to make the app executable? 如何更改此名称以使应用程序可执行?

EDIT: This is the core data initialization code inside my AppDelegate.Swift : 编辑:这是我AppDelegate.Swift内部的核心数据初始化代码:

// MARK: - Core Data stack

lazy var persistentContainer: NSPersistentContainer = {
    /*
     The persistent container for the application. This implementation
     creates and returns a container, having loaded the store for the
     application to it. This property is optional since there are legitimate
     error conditions that could cause the creation of the store to fail.
    */

    let container = NSPersistentContainer(name: "Data")


    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    return container
}()

// MARK: - Core Data Saving support

func saveContext () {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

It's a production app and the user should not lose any data after the update. 这是一个生产应用程序,用户在更新后不应丢失任何数据。

You mentioned in a comment that you have some transformable attributes. 您在评论中提到您具有一些可变形的属性。 This is consistent with your error message, since [NSKeyedUnarchiver decodeObjectForKey:] is part of NSCoding , and since Core Data uses NSCoding with transformable attributes. 这与您的错误消息一致,因为[NSKeyedUnarchiver decodeObjectForKey:]NSCoding一部分,并且由于Core Data使用具有可转换属性的NSCoding

This isn't a Core Data problem. 这不是核心数据问题。 You'd get the same error if you used NSCoding on the values of those attributes and wrote the result to a file. 如果对这些属性的值使用NSCoding并将结果写入文件,则会收到相同的错误。 In Swift, the full name of a class is something like AppName.ClassName . 在Swift中,类的全名类似于AppName.ClassName If AppName doesn't match, NSCoding can't decode the object. 如果AppName不匹配,则NSCoding无法解码该对象。 You saved objects with a name like OLD_PROJECTNAME.SomeObject , but now your class name is something like NEW_PROJECTNAME.SomeObject . 您以OLD_PROJECTNAME.SomeObject类的名称保存了对象,但是现在您的类名是NEW_PROJECTNAME.SomeObject NSCoding can't handle that on its own. NSCoding处理。 You need to help it. 您需要帮助。

To fix this, you need to tell the archiving system what class to use. 要解决此问题,您需要告诉归档系统要使用的类。 You can do that with the NSKeyedUnarchiver class method setClass(_:forClassName:) . 您可以使用NSKeyedUnarchiver类方法setClass(_:forClassName:)做到这setClass(_:forClassName:) You might have to experiment a little to get the syntax right but you'll have something like 您可能需要做一些尝试才能正确使用语法,但是您会遇到类似

NSKeyedUnarchiver.setClass(SomeClass.self, forClassName:"OLD_PROJECT_NAME.SomeObject")

You must do this before you attempt to create any objects that use this class so that it will affect how those objects are created. 在尝试创建使用此类的任何对象之前,必须执行此操作,以免影响创建这些对象的方式。 Since you're using Core Data that means before doing anything at all that touches Core Data in any way. 由于您正在使用Core Data,因此意味着在做任何以任何方式接触Core Data的事情之前。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM