39

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 something like

for attribute in Person {
     println("\(attribute): \(attribute.value)")
}

the output would be for example:

name: Bob
lastname: Max
age: 20
1

5 Answers 5

71

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 later
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

Sign up to request clarification or add additional context in comments.

2 Comments

any idea how to also get the properties of the superclass?
It's ignoring/Limited var favoriteFood: String { return "Lemon Cake" }
13

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.

1 Comment

assuming that my class is implementing a protocol. How do I get the properties of the protocol/superclass
5

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())")

Comments

3

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)

Comments

3

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")
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.