如何在Swift中列出一个类的所有变量

16

有没有一种方法可以在 Swift 中列出类的所有变量?

例如:

class foo {
   var a:Int? = 1
   var b:String? = "John"
}

我希望像这样列出它:[a:1, b:"John"]


非常相似(重复?)的问题:Swift中类的属性列表 - Martin R
像这样:https://dev59.com/aGAf5IYBdhLWcg3wQg1t?哦 - 看起来是的 :-) - qwerty_so
我确实尝试过,但对我没有用,在我的情况下,我需要获取变量而不是属性。 - Hasan Akgün
你的示例列出了属性。 - qwerty_so
以上示例需要是NSObject才能工作。我猜如果没有的话,你就倒霉了。 - qwerty_so
4个回答

23

如何在Swift 3.0中使用递归进行操作:

import Foundation

class FirstClass {
    var name = ""
    var last_name = ""
    var age = 0
    var other = "abc"

    func listPropertiesWithValues(reflect: Mirror? = nil) {
        let mirror = reflect ?? Mirror(reflecting: self)
        if mirror.superclassMirror != nil {
            self.listPropertiesWithValues(reflect: mirror.superclassMirror)
        }

        for (index, attr) in mirror.children.enumerated() {
            if let property_name = attr.label {
                //You can represent the results however you want here!!!
                print("\(mirror.description) \(index): \(property_name) = \(attr.value)")
            }
        }
    }

}


class SecondClass: FirstClass {
    var yetAnother = "YetAnother"
}

var second = SecondClass()
second.name  = "Name"
second.last_name = "Last Name"
second.age = 20

second.listPropertiesWithValues()

结果:

Mirror for FirstClass 0: name = Name
Mirror for FirstClass 1: last_name = Last Name
Mirror for FirstClass 2: age = 20
Mirror for FirstClass 3: other = abc
Mirror for SecondClass 0: yetAnother = YetAnother

从ObjC转换的类(例如,FirstClass在ObjC中)中,“label”不知何故为nil。 - allenlinli
这个 ObjC 的解决方案有效。 https://dev59.com/OmYr5IYBdhLWcg3wJ2-U - allenlinli

8
以下应使用反射生成成员和值列表。请参见http://swiftstub.com/836291913/上的范例。
class foo {
   var a:Int? = 1
   var b:String? = "John"
}
let obj = foo()
let reflected = reflect(obj)
var members = [String: String]()
for index in 0..<reflected.count {
    members[reflected[index].0] = reflected[index].1.summary
}
println(members)

输出:

[b: John, a: 1]

这个答案 https://dev59.com/JGAg5IYBdhLWcg3wBXAR#24069875 有一条评论,其中包含一个指向 https://gist.github.com/mchambers/67640d9c3e2bcffbb1e2 的链接,在那里(如果我理解正确的话)实际值被检索,而不仅仅是字符串描述。 - Martin R
1
不知道这个。谢谢!如果写成 for index in 0..<reflected.count {,你的 for 循环会更加 "Swifty"。 - qwerty_so

3
也许有点晚了,但是这个使用反射和Mirror的解决方案是100%有效的:
class YourClass : NSObject {
    var title:String
    var url:String

    ...something other...

    func properties() -> [[String: Any]] {
        let mirror = Mirror(reflecting: self)

        var retValue = [[String:Any]]()
        for (_, attr) in mirror.children.enumerated() {
            if let property_name = attr.label as String! {
                retValue.append([property_name:attr.value])
            }
        }
        return retValue
    }
}

在你的代码中的某个地方...

var example = MoreRow(json: ["title":"aTitle","url":"anURL"])
print(example.listPropertiesWithValues())

0

我从这里得到了线索。https://medium.com/@YogevSitton/use-auto-describing-objects-with-customstringconvertible-49528b55f446

这是一个关于Swift 4.0的演示。

import Foundation

extension CustomStringConvertible {
    var description : String {
        var description: String = ""
        if self is AnyObject {  // unsafeAddressOf((self as! AnyObject))
            description = "***** \(type(of: self)) - <\(Unmanaged.passUnretained(self as AnyObject).toOpaque())>***** \n"
        } else {
            description = "***** \(type(of: self)) *****\n"
        }
        let selfMirror = Mirror(reflecting: self)
        for child in selfMirror.children {
            if let propertyName = child.label {
                description += "\(propertyName): \(child.value)\n"
            }
        }
        return description
    }
}

extension NSObject {
    var description: String {
        var description: String = ""
        if self is AnyObject {  // unsafeAddressOf((self as! AnyObject))
            description = "***** \(type(of: self)) - <\(Unmanaged.passUnretained(self as AnyObject).toOpaque())>***** \n"
        } else {
            description = "***** \(type(of: self)) *****\n"
        }
        let selfMirror = Mirror(reflecting: self)
        for child in selfMirror.children {
            if let propertyName = child.label {
                description += "\(propertyName): \(child.value)\n"
            }
        }
        return description
    }
}

class AA: CustomStringConvertible {
    var a: String = "aaa"
}

class BB: NSObject {
    var b: String = "bbb"
}

let  aa = AA()
print(aa)

let  bb = BB()
print(bb.description)

输出 --

***** AA - <0x00000001001038e0>***** 
a: aaa

***** BB - <0x0000000100103310>***** 
b: bbb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接