在测试新Codable如何与NSCoding进行交互时,我已经将使用包含Codable结构的Class的NSCoding放在一起进行游乐场测试。白衣
struct Unward: Codable {
var id: Int
var job: String
}
class Akward: NSObject, NSCoding {
var name: String
var more: Unward
init(name: String, more: Unward) {
self.name = name
self.more = more
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(more, forKey: "more")
}
required init?(coder aDecoder: NSCoder) {
name = aDecoder.decodeObject(forKey: "name") as? String ?? ""
more = aDecoder.decodeObject(forKey: "more") as? Unward ?? Unward(id: -1, job: "unk")
super.init()
}
}
var upone = Unward(id: 12, job: "testing")
var adone = Akward(name: "Adrian", more: upone)
上述内容已被Playground接受,并且不会产生任何编译器错误。
但是,如果我尝试保存adone,那么:
let encodeit = NSKeyedArchiver.archivedData(withRootObject: adone)
游乐场迅速崩溃并出现错误:
错误:执行被中断,原因:EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0)。
为什么呢? 有没有办法让NSCoding类包含一个Codable结构?
答案 0 :(得分:2)
您获得的实际错误是:
- [_ SwiftValue encodeWithCoder:]:无法识别的选择器发送到实例
这是来自这条线:
aCoder.encode(more, forKey: "more")
问题的原因是more
(Unward
类型)不符合NSCoding
。但是Swift struct
无法符合NSCoding
。除了符合Unward
之外,您还需要将NSObject
更改为扩展NSCoding
的类。这些都不会影响符合Codable
的能力。
这是您更新的课程:
class Unward: NSObject, Codable, NSCoding {
var id: Int
var job: String
init(id: Int, job: String) {
self.id = id
self.job = job
}
func encode(with aCoder: NSCoder) {
aCoder.encode(id, forKey: "id")
aCoder.encode(job, forKey: "job")
}
required init?(coder aDecoder: NSCoder) {
id = aDecoder.decodeInteger(forKey: "id")
job = aDecoder.decodeObject(forKey: "job") as? String ?? ""
}
}
class Akward: NSObject, Codable, NSCoding {
var name: String
var more: Unward
init(name: String, more: Unward) {
self.name = name
self.more = more
}
func encode(with aCoder: NSCoder) {
aCoder.encode(name, forKey: "name")
aCoder.encode(more, forKey: "more")
}
required init?(coder aDecoder: NSCoder) {
name = aDecoder.decodeObject(forKey: "name") as? String ?? ""
more = aDecoder.decodeObject(forKey: "more") as? Unward ?? Unward(id: -1, job: "unk")
}
}
您的测试值:
var upone = Unward(id: 12, job: "testing")
var adone = Akward(name: "Adrian", more: upone)
您现在可以归档和取消归档:
let encodeit = NSKeyedArchiver.archivedData(withRootObject: adone)
let redone = NSKeyedUnarchiver.unarchiveObject(with: encodeit) as! Akward
你可以编码和解码:
let enc = try! JSONEncoder().encode(adone)
let dec = try! JSONDecoder().decode(Akward.self, from: enc)