簡體   English   中英

為什么 `Mirror.child.label` 字段不能正確處理自引用類?

[英]Why is the `Mirror.child.label` field not handling self-referential classes properly?

我在 Swift 中使用反射將通用 object (Any) 寫入 Swift 中的字典; 用於教育和生產目的。

該代碼有效,但我的一項測試表明,對於自引用類,它無法正常工作。

訪問與class類型相同的引用成員字段時,Mirror.child.label字段在訪問成員變量之前返回一個值some作為字典鍵。

一個很好的例子:

class Node{
  var next: Node!
  var val: Int = 0

init(_ val: Int){
self.val = val
}

}
  
 
let node = Node(4)
node.next = Node(5)
node.next.next = Node(6)


print("node.toDictionary: " , toDictionary(obj: node))

output 是:

node.toDictionary:  ["val": 4, "next": ["some": ["next": ["some": ["val": 6, "next": [:]]], "val": 5]]]

不用說,預期的 output 是:

["next": ["next": ["val": 6],"val": 5],"val": 4]

產生此錯誤的toDictionary的最小代碼是:

func toDictionary(obj: Any) -> [String:Any] {
    var dict = [String:Any]()
    let otherObj = Mirror(reflecting: obj)
    for child in otherObj.children {
        if let key = child.label {
          
            if child.value is String || child.value is Character || child.value is Bool
                || child.value is Int  || child.value is Int8  || child.value is Int16  || child.value is Int32 || child.value is Int64
                || child.value is UInt  || child.value is UInt8  || child.value is UInt16  || child.value is UInt32 || child.value is UInt64
                || child.value is Float  || child.value is Float32 || child.value is Float64 || child.value is Double
            {
                dict[key] = child.value
            }
            else if child.value is [String] || child.value is [Character] || child.value is [Bool]
                || child.value is [Int]  || child.value is [Int8]  || child.value is [Int16]  || child.value is [Int32] || child.value is [Int64]
                || child.value is [UInt]  || child.value is [UInt8]  || child.value is [UInt16]  || child.value is [UInt32] || child.value is [UInt64]
                || child.value is [Float]  || child.value is [Float32] || child.value is [Float64] || child.value is [Double]{
                
                let array = child.value as! [Any]
                
                
                dict[key] = array
                
                
            }else if child.value is [Any]{
                 let array = child.value as! [Any]
                 var arr:[Any] = []
                for any in array{
                    arr.append(toDictionary(obj: any))
                }
                dict[key] = arr
            }
            else{
                dict[key] = toDictionary(obj: child.value)
            }
            
        }
    }
    return dict
}

為什么Mirror.child.label字段不能正確處理自引用類?

原因是var: next: Node! 是一個隱式展開的可選項,在許多情況下,它們被視為常規選項,例如

所以node.next的值實際上是Optional<Node>.some(nextNode) ,這會導致創建字典中的["some": ...]

該效果與自引用屬性無關,如以下示例所示:

class Bar {
    let value = 1
}

class Foo {
    var bar: Bar! = Bar()
}

let foo = Foo()
print(toDictionary(obj: foo))
// ["bar": ["some": ["value": 1]]]

暫無
暫無

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

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