我想使用NSKeyedArchiver和NSKeyedUnarchiver序列化和反序列化我的GKGraphNode子类的对象。所以我尝试以下方法:
//: Playground - noun: a place where people can play
import GameplayKit
class MyGraphNode: GKGraphNode {
static let textCodingKey = "TextCodingKey"
let text: String
override convenience init() {
self.init(text: "Default Text")
}
init(text: String) {
self.text = text
super.init()
}
required init?(coder aDecoder: NSCoder) {
text = aDecoder.decodeObject(forKey: MyGraphNode.textCodingKey) as! String
super.init(coder: aDecoder)
}
override func encode(with aCoder: NSCoder) {
super.encode(with: aCoder)
aCoder.encode(text, forKey: MyGraphNode.textCodingKey)
}
}
let text = "Test Text"
let graphNode = MyGraphNode(text: text)
let data = NSKeyedArchiver.archivedData(withRootObject: graphNode)
if let unarchivedGraphNode = NSKeyedUnarchiver.unarchiveObject(with: data) as? MyGraphNode {
print("Text: \(unarchivedGraphNode.text)")
}
不幸的是,该示例仅打印默认文本而不打印预期的测试文本:
文字:默认文字
首先我省略了便利初始化器。但在这种情况下,它崩溃了这个错误:
错误:执行被中断,原因:EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP,subcode = 0x0)。这个过程一直留在了 它被中断的点,使用"线程返回-x"回到 表达评估前的状态。
GKGraphNodeSubclass.playground:5:7:致命错误:使用 未实现的初始化程序' init()'上课 ' __ lldb_expr_58.MyGraphNode'
有人可以解释为什么在反序列化期间忽略测试文本吗? 或者为什么我必须添加便利初始化器?
答案 0 :(得分:0)
“text”属性最终被“super.init(coder:aDecoder)”重置,大概是因为它在内部调用了“init()”,最终会在你方便的时候“init()”结束。这在Swift中是非法的,但它在Obj-C中是合法的,它没有相同的严格初始化规则。
解决方案是在super.init(编码器:)之后初始化“text”,而不是之前。这意味着您不能使用“let”属性
为了修复我的例子,我改变了变量声明和NSCoding初始化器,如下所示:
var text: String!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
text = aDecoder.decodeObject(forKey: MyGraphNode.textCodingKey) as! String
}
答案 1 :(得分:0)
我同意鲁本,但有一点补充
可能还需要重写init()以确保它存在。由于Swift的初始化规则很严格
override init() {
super.init()
}