我有一个继承自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]
可能存在问题,但编译器还没有抱怨......
答案 0 :(得分:1)
我自己刚刚找到了解决方案:关键是将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")
}
}
答案 1 :(得分:0)
我知道您的标题指定了Swift 2,但仅供参考,对于我正在处理的类似问题,我发现在 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")
}
}