[英]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.