如何使用NSKeyedArchiver/Unarchiver序列化反序列化GKGraphNode子类
解决自定义GKGraphNode子类的NSKeyedArchiver序列化问题
我来帮你把这个自定义MyGraphNode的序列化/反序列化代码补全并解释清楚!因为GKGraphNode遵循NSCoding协议,所以你的子类必须完整实现encode(with:)和required init?(coder:)两个方法才能正常序列化,你的代码里刚好缺了这部分的完整实现。
完整的MyGraphNode实现代码
//: 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() } // MARK: - NSCoding 实现 required init?(coder aDecoder: NSCoder) { // 先解码自定义的text属性,做类型校验避免崩溃 guard let decodedText = aDecoder.decodeObject(forKey: Self.textCodingKey) as? String else { return nil } self.text = decodedText // 必须调用父类初始化方法,确保GKGraphNode自身的属性也被反序列化 super.init(coder: aDecoder) } override func encode(with aCoder: NSCoder) { // 先编码自定义的text属性 aCoder.encode(text, forKey: Self.textCodingKey) // 必须调用父类encode方法,保存GKGraphNode的图结构状态 super.encode(with: aCoder) } }
测试序列化与反序列化的验证代码
你可以在Playground里添加这段代码,验证功能是否正常:
// 创建自定义节点实例 let originalNode = MyGraphNode(text: "Hello Custom Graph Node") // 序列化:将节点转为Data guard let archivedData = try? NSKeyedArchiver.archivedData(withRootObject: originalNode, requiringSecureCoding: false) else { fatalError("序列化失败") } // 反序列化:将Data转回节点实例 guard let unarchivedNode = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(archivedData) as? MyGraphNode else { fatalError("反序列化失败") } // 打印结果验证 print("原始节点文本:\(originalNode.text)") print("反序列化后节点文本:\(unarchivedNode.text)")
关键注意事项
- 必须调用父类的对应方法:
GKGraphNode内部维护着图的连接关系等状态,如果不调用super.encode(with:)和super.init(coder:),这些状态会丢失,反序列化后的节点会不完整。 - 解码时做类型校验:用
guard确保解码出的对象是String类型,避免类型不匹配导致运行时崩溃。 - 编码键保持统一:用静态常量
textCodingKey确保编码和解码使用同一个键,避免拼写错误导致的属性丢失。
内容的提问来源于stack exchange,提问作者Ruben
相关产品推荐
相关产品推荐

