使用NSKeyedUnarchiver反序列化GKGraphNode的子类

时间:2018-03-18 21:56:20

标签: swift nscoding nskeyedunarchiver gameplay-kit

我想使用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'

有人可以解释为什么在反序列化期间忽略测试文本吗? 或者为什么我必须添加便利初始化器?

2 个答案:

答案 0 :(得分:0)

我在Apple Developer Forum

中得到了帮助
  

“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()
}