使用 NSKeyedUnarchiver 反序列化 GKGraphNode 的子类
Deserialize subclass of GKGraphNode using NSKeyedUnarchiver
我想使用 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)")
}
不幸的是,该示例仅打印默认文本而不是预期的测试文本:
Text: Default Text
首先我省略了便利初始化器。但在这种情况下,它因以下错误而崩溃:
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION
(code=EXC_I386_INVOP, subcode=0x0). The process has been left at the
point where it was interrupted, use "thread return -x" to return to
the state before expression evaluation.
GKGraphNodeSubclass.playground: 5: 7: Fatal error: Use of
unimplemented initializer 'init()' for class
'__lldb_expr_58.MyGraphNode'
谁能解释为什么在反序列化过程中忽略了测试文本?
或者为什么我必须添加便利初始化程序?
我在 Apple Developer Forum 中得到了帮助:
The "text" property is ending up being reset by "super.init(coder: aDecoder)", presumably because that calls "init()" internally, and that ends up at your convenience "init ()". This would be illegal in Swift, but it's legal in Obj-C, which doesn't have the same strict initialization rules.
The solution is to initialize "text" after the super.init(coder:), rather than before. This means you can't use a "let" property
为了修复我的示例,我更改了变量声明和 NSCoding 初始值设定项,如下所示:
var text: String!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
text = aDecoder.decodeObject(forKey: MyGraphNode.textCodingKey) as! String
}
我同意 Ruben 的观点,但有一点补充
可能还需要覆盖 init() 以确保它存在。由于Swift
严格的初始化规则
override init() {
super.init()
}
我想使用 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)")
}
不幸的是,该示例仅打印默认文本而不是预期的测试文本:
Text: Default Text
首先我省略了便利初始化器。但在这种情况下,它因以下错误而崩溃:
error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0). The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.
GKGraphNodeSubclass.playground: 5: 7: Fatal error: Use of unimplemented initializer 'init()' for class '__lldb_expr_58.MyGraphNode'
谁能解释为什么在反序列化过程中忽略了测试文本?
或者为什么我必须添加便利初始化程序?
我在 Apple Developer Forum 中得到了帮助:
The "text" property is ending up being reset by "super.init(coder: aDecoder)", presumably because that calls "init()" internally, and that ends up at your convenience "init ()". This would be illegal in Swift, but it's legal in Obj-C, which doesn't have the same strict initialization rules.
The solution is to initialize "text" after the super.init(coder:), rather than before. This means you can't use a "let" property
为了修复我的示例,我更改了变量声明和 NSCoding 初始值设定项,如下所示:
var text: String!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
text = aDecoder.decodeObject(forKey: MyGraphNode.textCodingKey) as! String
}
我同意 Ruben 的观点,但有一点补充
可能还需要覆盖 init() 以确保它存在。由于Swift
严格的初始化规则override init() {
super.init()
}