Swift 3 - NSCoding 没有从 NSObject 继承的烦恼

Swift 3 - NSCoding without the annoyance of inheriting from NSObject

NSKeyedArchiver 崩溃

2016-10-06 17:06:06.713 MessagesExtension[24473:2175316] *** NSForwarding: 
warning: object 0x61800009d740 of class '' does not implement 
methodSignatureForSelector: -- trouble ahead
Unrecognized selector -[MessagesExtension.Model replacementObjectForKeyedArchiver:]

我创建了一个名为 Coding 的协议,其全部目的是简化 NSCodingNSKeyedArchiver 而无需使用 Objective-C 的碎片。

protocol Coding {
    static var directory: FileManager.SearchPathDirectory { get }
    static var domainMask: FileManager.SearchPathDomainMask { get }

    func encode() -> [String: AnyObject]
    init()
    init?(dict: [String: AnyObject]?)
}

extension Coding {
    static var directory: FileManager.SearchPathDirectory {
        return .documentDirectory
    }

    static var domainMask: FileManager.SearchPathDomainMask {
        return .userDomainMask
    }

    static var directoryURL: String? {
        return NSSearchPathForDirectoriesInDomains(Self.directory, Self.domainMask, true).last?.appending("/")
    }

    func save(to path: String) -> Bool {
        guard let url = Self.directoryURL else { return false }

        return NSKeyedArchiver.archiveRootObject(self.encode() as NSDictionary, toFile: url + path)
    }

    static func create(from path: String) -> Self {
        guard let url = Self.directoryURL,
              let dict = NSKeyedUnarchiver.unarchiveObject(withFile: url + path) as? [String: AnyObject] else { return self.init() }

        return self.init(dict: dict) ?? self.init()
    }
}

此协议和扩展旨在简化 NSCoding 并允许在 Struts 上使用该协议。然而,当我试图 保存 对象时,我 运行 陷入了上面的崩溃。

更具体地说,我在

的 return 行遇到了崩溃
func save(to path: String) -> Bool {
    guard let url = Self.directoryURL else { return false }

    return NSKeyedArchiver.archiveRootObject(self.encode() as NSDictionary, toFile: url + path)
}

我感觉它与 NSDictionary 有关,但我不确定如何进行。

有什么建议吗??

基金会归档系统(NSCoding 和相关类型)是在 Objective-C 很久以前设计和实施的(其中一部分已有 20 多年的历史),预计 "objects" 成为 NSObject 的实例。尝试使用它来编码包含非 NSObject 类对象的对象图是不现实的。您很可能能够简化它在 Swift 中的使用,但是您将需要确保归档程序认为是 NSObject 的所有内容都实现了 NSObject API。由于没有归档程序使用哪些部分的文档,唯一明智的选择是继承 NSObject.

当然我可能是错的,但你没有向我们展示代码的相关部分(特别是 encode 的实现)。

Vishal S 整理了一篇非常好的文章,介绍了(当前)在结构中保存数据的不同方式。

Archiving and Unarchiving Swift Structure Instances

或者如 Vishal 所说:

Swift introduced a tremendous anmount of type-safety. But, archiving and unarchiving always loses the types of the objects. Until a better way comes along to do this by supporting all of Swift’s principles, we should make do with what we have.

当然有人可能会建议 Apple Gurus 投入一点精力来开发一种结构(和类型)友好的方式来保存您的数据 (!)。