Swift 树结构、编码和访问节点
Posted
技术标签:
【中文标题】Swift 树结构、编码和访问节点【英文标题】:Swift Tree Structure, encoding and accessing nodes 【发布时间】:2022-01-23 00:56:36 【问题描述】:我无法弄清楚为什么以下内容不运行。目标是创建一个可以保存到 json 文件的引用类型的树结构,但是下面的 Playground 代码无法运行。
根节点有一个 nil 父节点,但我认为编码器忽略了 nil 值。在我的应用程序中,我得到一个 EXC_BAD_ACCESS。这是否需要用结构而不是类来完成,如果是这样,有没有办法在不遍历整个树的情况下访问特定节点?任何帮助表示赞赏。
import Cocoa
final class Node: Codable
var id: UUID
var data: [MyData]
var children: [Node]
var parent: Node? = nil
init()
self.id = UUID()
self.data = []
self.children = []
func add(data: MyData)
data.parent = self
self.data.append(data)
func add(child: Node)
child.parent = self
self.children.append(child)
final class MyData: Codable
var id: UUID
var label: String
var value: String
var parent: Node? = nil
init(label: String, value: String)
self.id = UUID()
self.label = label
self.value = value
var root = Node()
root.add(data: MyData(label: "label 1", value: "value 1"))
root.add(data: MyData(label: "label 2", value: "value 2"))
var child = Node()
child.add(data: MyData(label: "label 3", value: "value 3"))
root.add(child: child)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let json = try encoder.encode(root)
print(String(data: json, encoding: .utf8)!)
【问题讨论】:
【参考方案1】:问题在于默认情况下Codable
尝试编码/解码符合类型的所有属性。这意味着孩子尝试编码/解码他们的父母,父母也包含孩子,因此导致无限循环。
您需要通过提供符合CodingKey
的类型手动指定要编码/解码的属性。通过从Node.CodingKeys
和MyData.CodingKeys
中省略parent
属性,您可以解决无限循环。
import Foundation
final class Node: Codable
let id = UUID()
var data: [MyData]
var children: [Node]
var parent: Node? = nil
init()
self.data = []
self.children = []
func add(data: MyData)
data.parent = self
self.data.append(data)
func add(child: Node)
child.parent = self
self.children.append(child)
private enum CodingKeys: String, CodingKey
case data
case children
final class MyData: Codable
let id = UUID()
var label: String
var value: String
var parent: Node? = nil
init(label: String, value: String)
self.label = label
self.value = value
private enum CodingKeys: String, CodingKey
case label
case value
var root = Node()
root.add(data: MyData(label: "label 1", value: "value 1"))
root.add(data: MyData(label: "label 2", value: "value 2"))
var child = Node()
child.add(data: MyData(label: "label 3", value: "value 3"))
root.add(child: child)
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let json = try encoder.encode(root)
print(String(data: json, encoding: .utf8)!)
【讨论】:
太棒了!就是这样。现在就像一个魅力 - 感谢您的澄清。以上是关于Swift 树结构、编码和访问节点的主要内容,如果未能解决你的问题,请参考以下文章