NSKeyedArchiver并在目标之间共享自定义类

问题描述 投票:1回答:1

我的应用程序使用自定义类作为其数据模型:

class Drug: NSObject, NSCoding {
    // Properties, methods etc...
}

我刚刚创建了Today扩展程序,需要从中访问用户的数据,因此我使用NSCoding将数据保留在应用程序容器和共享容器中。这些是主应用程序中的保存和加载功能:

func saveDrugs() {
    // Save to app container
    let isSuccessfulSave = NSKeyedArchiver.archiveRootObject(drugs, toFile: Drug.ArchiveURL.path)
    if isSuccessfulSave {
        print("Drugs successfully saved locally")
    } else {
        print("Error saving drugs locally")
    }

    // Save to shared container for extension
    let isSuccessfulSaveToSharedContainer = NSKeyedArchiver.archiveRootObject(drugs, toFile: Drug.SharedArchiveURL.path)
    if isSuccessfulSaveToSharedContainer {
        print("Drugs successfully saved to shared container")
    } else {
        print("Error saving drugs to shared container")
    }
}

func loadDrugs() -> [Drug]? {
    return NSKeyedUnarchiver.unarchiveObject(withFile: Drug.ArchiveURL.path) as? [Drug]
}

我遇到了类命名空间的问题,在今天的扩展中,NSKeyedUnarchiver无法正确解码该对象,因此我在类定义之前使用了this answer并添加了@objc

@objc(Drug)
class Drug: NSObject, NSCoding {
    // Properties, methods etc...
}

这完美地解决了问题。但是,这将是我的应用程序的1.3版,并且似乎这破坏了预先存在的数据的取消存档过程(正如我认为的那样)。

处理这种情况的最佳方法是什么,就像我刚刚进行更改一样,新版本的应用程序将对现有用户崩溃!

我找不到关于此的任何其他答案,并且我不确定NSKeyedArchiver.setClass()方法是否相关,也不确定在哪里使用它。

非常感谢您的帮助。谢谢。

ios swift ios-app-extension nskeyedarchiver nskeyedunarchiver
1个回答
4
投票

这正是NSKeyedUnarchiver.setClass(_:forClassName:)的用例-您可以通过将当前类与其旧名称相关联来向前迁移旧类:

NSKeyedUnarchiver.setClass(_:forClassName:)

或者,您可以提供一个符合let unarchiver = NSKeyedUnarchiver(...) unarchiver.setClass(Drug.self, forClassName: "myApp.Drug") // unarchive as appropriate 并提供NSKeyedUnarchiverDelegate的委托,但这在这种情况下可能会显得过头了。


请记住,这适用于向前迁移旧数据。如果您有新版本的应用程序需要将数据发送到旧版本的应用程序,则在存档方面,您需要做的事情与之类似-继续用NSKeyedUnarchiverDelegate

用旧名称编码新类。
unarchiver(_:cannotDecodeObjectOfClassName:originalClasses:)

如果您有向后兼容性问题,那么很遗憾,只要有旧版应用程序的用户,您就可能需要继续使用旧名称。

© www.soinside.com 2019 - 2024. All rights reserved.