[英]Encoding/Decoding an array of objects which implements a protocol in Swift 2
I have got a class that inherits from NSObject
and I want it to be NSCoding
compliant. 我有一个继承自
NSObject
的类,我希望它与NSCoding
兼容。 But I ran into trouble while encoding an array of objects which should implement a protocol. 但是我在编码应该实现协议的对象数组时遇到麻烦。
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")
}
}
For aCoder.encodeObject(myCollection, forKey: "collection")
I get the error: 对于
aCoder.encodeObject(myCollection, forKey: "collection")
我收到错误:
Cannot convert value of type '[MyProtocol]' to expected argument type 'AnyObject?'
OK, a protocol obviously is not an instance of a class and so it isn't AnyObject?
好的,协议显然不是类的实例,因此不是
AnyObject?
but I've no idea how to fix that. 但我不知道如何解决。 Probably there is a trick that I'm not aware?
也许有一个我不知道的把戏? Or do you do archiving/serialization differently in Swift as in Objective-C?
还是在Swift中和在Objective-C中进行归档/序列化不同?
There's probably a problem with let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
可能存在问题let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
, too but the compiler doesn't complain yet… let collection = aDecoder.decodeObjectForKey("collection") as! [MyProtocol]
也是如此,但是编译器还没有抱怨……
I've just found the solution myself: The key is to map myCollection
into [AnyObject]
and vice-versa, like so: 我自己找到了解决方案:关键是将
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")
}
}
I know your title specifies Swift 2, but just for reference, for a similar problem I was working on, I found that in Swift 3 , you don't need to convert anymore to AnyObject. 我知道您的标题指定了Swift 2,但仅供参考,对于我正在处理的类似问题,我发现在Swift 3中 ,您不再需要转换为AnyObject。
The following works for me in Swift 3 (using your example): 以下内容适用于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")
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.