代码之家  ›  专栏  ›  技术社区  ›  Jens Kohl

对Swift 2中实现协议的对象数组进行编码/解码

  •  1
  • Jens Kohl  · 技术社区  · 9 年前

    我有一个继承自 NSObject 我希望它是 NSCoding 顺从的但是我在编码应该实现协议的对象数组时遇到了麻烦。

    protocol MyProtocol {
        var myDescription: String { get }
    }
    
    class DummyClass: NSObject, NSCopying, MyProtocol {
        var myDescription: String {
            return "Some description"
        }
    
        func encodeWithCoder(aCoder: NSCoder) {
            // does not need to do anything since myDescription is a computed property
        }
    
        override init() { super.init() }
        required init?(coder aDecoder: NSCoder) { super.init() }
    }
    
    class MyClass: NSObject, NSCoding {
        let myCollection: [MyProtocol]
    
        init(myCollection: [MyProtocol]) {
            self.myCollection = myCollection
    
            super.init()
        }
    
        required convenience init?(coder aDecoder: NSCoder) {
            let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
    
            self.init(myCollection: collection)
        }
    
        func encodeWithCoder(aCoder: NSCoder) {
            aCoder.encodeObject(myCollection, forKey: "collection")
        }
    }
    

    对于 aCoder.encodeObject(myCollection, forKey: "collection") 我得到错误:

    Cannot convert value of type '[MyProtocol]' to expected argument type 'AnyObject?'
    

    好吧,协议显然不是类的实例,所以它不是 AnyObject? 但我不知道该怎么解决。也许有一个我不知道的把戏?或者,您在Swift中的归档/序列化与在Objective-C中的不同吗?

    可能有问题 let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol] ,但编译器还没有抱怨

    2 回复  |  直到 9 年前
        1
  •  1
  •   Jens Kohl    9 年前

    我自己刚刚找到了解决方案:关键是地图 myCollection 进入 [AnyObject] 反之亦然:

    class MyClass: NSObject, NSCoding {
        let myCollection: [MyProtocol]
    
        init(myCollection: [MyProtocol]) {
            self.myCollection = myCollection
    
            super.init()
        }
    
        required convenience init?(coder aDecoder: NSCoder) {
            let collection1 = aDecoder.decodeObjectForKey("collection") as! [AnyObject]
    
            let collection2: [MyProtocol] = collection1.map { $0 as! MyProtocol }
    
    
            self.init(myCollection: collection2)
        }
    
        func encodeWithCoder(aCoder: NSCoder) {
            let aCollection: [AnyObject] = myCollection.map { $0 as! AnyObject }
    
            aCoder.encodeObject(aCollection, forKey: "collection")
        }      
    }
    
        2
  •  0
  •   davejlin    8 年前

    我知道您的标题指定了Swift2,但仅供参考,对于我正在处理的类似问题,我发现在 Swift银行3 ,您不需要再转换为AnyObject。

    以下内容适用于我 Swift银行3 (使用您的示例):

    class MyClass: NSObject, NSCoding {
        let myCollection: [MyProtocol]
    
        init(myCollection: [MyProtocol]) {
            self.myCollection = myCollection
            super.init()
        }
    
        required convenience init?(coder aDecoder: NSCoder) {
            let collection = aDecoder.decodeObject(forKey: "collection") as! [MyProtocol]    
            self.init(myCollection: collection)
        }
    
        func encodeWithCoder(aCoder: NSCoder) {    
            aCoder.encode(aCollection, forKey: "collection")
        }      
    }