iterate over object class attributes in Swift

前端 未结 5 1972
星月不相逢
星月不相逢 2020-11-30 01:28

Is there a Simple way in Swift to iterate over the attributes of a class.

i.e. i have a class Person, and it has 3 attributes: name, lastname, age.

is there

相关标签:
5条回答
  • 2020-11-30 01:39

    They have removed reflect within Swift 2.0. This is how I am enumerating attributes and values.

    class People {
        var name = ""
        var last_name = ""
        var age = 0
    }
    
    var user = People()
    user.name  = "user name"
    user.last_name = "user lastname"
    user.age = 20
    
    let mirrored_object = Mirror(reflecting: user)
    
    // Swift 2
    for (index, attr) in mirrored_object.children.enumerate() {
        if let property_name = attr.label as String! {
            print("Attr \(index): \(property_name) = \(attr.value)")
        }
    }
    
    // Swift 3 and after
    for (index, attr) in mirrored_object.children.enumerated() {
        if let property_name = attr.label as String! {
            print("Attr \(index): \(property_name) = \(attr.value)")
        }
    }
    

    Output:
    Attr 0: name = user name
    Attr 1: last_name = user lastname
    Attr 2: age = 20

    0 讨论(0)
  • 2020-11-30 01:50

    Here's Swift 5 version of object description:

    class TestClass: CustomStringConvertible {
    
        public var description: String {
            return Mirror(reflecting: self).children.compactMap({
                if let label = $0.label {
                    return "\(label): \($0.value)"
                }
                
                return ""
            }).joined(separator: "\n")
        }
    }
    
    0 讨论(0)
  • 2020-11-30 01:51

    Yes, if you just need to print properties of a struct or class, and the properties are simple types like String and Int, you can use reflect and MirrorType.

    func print_properties(mirror: MirrorType) {
        for i in 0..<mirror.count {
            let (name, childMirror) = mirror[i]
            let value = childMirror.value
            println("\(i): \(name) = \(value)")
        }
    }
    
    struct Person {
        let first_name: String
        let last_name: String
        let age: Int
    }
    
    let john = Person(first_name:"John", last_name:"Doe", age:27)
    let mirror = reflect(john)
    print_properties(mirror)
    

    If you have nested structs, enums, you need to do a bit more work.

    0 讨论(0)
  • 2020-11-30 01:52

    As @mohacs suggested, You can provide a function Description in your required class like follows;

    func description() -> String{
    
            let mirrored_object = Mirror(reflecting: self)
            let str:NSMutableString = NSMutableString()
            for (index, attr) in mirrored_object.children.enumerated() {
                if let property_name = attr.label as String! {
                    str.append(" Attr \(index): \(property_name) = \(attr.value)")
                }
            }
            //print("desc=\(str)")
            return str as String
        }
    

    Then simple call this instance method

      let jsonOb:JsonModel = self.ObjArray[Index]
      print("jsonOb = \(jsonOb.description())")
    
    0 讨论(0)
  • 2020-11-30 01:55

    Apple didn't remove reflect,they just change it to _reflect,they also changed MirrorType to _MirrorType.
    The Swift 2.0 version of @Teemu Kurppa 's code:

    func print_properties(mirror: _MirrorType) {
      for i in 0..<mirror.count {
        let (name, childMirror) = mirror[i]
        let value = childMirror.value
        print("\(i): \(name) = \(value) ")
      }
    }
    
    struct Person {
        let first_name: String
        let last_name: String
        let age: Int
    }
    
    let john = Person(first_name:"John", last_name:"Doe", age:27)
    let mirror = _reflect(john)
    print_properties(mirror)
    
    0 讨论(0)
提交回复
热议问题