簡體   English   中英

Swift 樹結構,編碼和訪問節點

[英]Swift Tree Structure, encoding and accessing nodes

我無法弄清楚為什么以下不運行。 目標是創建一個具有引用類型的樹結構,可以將其保存到 json 文件中,但以下操場代碼無法運行。

根節點有一個 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)!)

問題是默認情況下Codable嘗試編碼/解碼符合類型的所有屬性。 這意味着孩子嘗試編碼/解碼他們的父母,父母也包含孩子,因此導致無限循環。

您需要通過提供符合CodingKey的類型來手動指定要編碼/解碼的屬性。 通過從Node.CodingKeysMyData.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)!)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM