Francisco Romero
Francisco Romero

Reputation: 13199

How to access to each attribute of an object array using a loop?

I have a Person object:

class Person{
    var name: String
    var city: String
    var country: String

    init(name: String, city: String, country: String){
        self.name = name
        self.city = city
        self.country = country
    }
}

and two arrays. One array of Person objects and one with the names of each of the attributes of the array.

var values = [Person]()
var attributes = ["name","city","country"]

and for example if I add two new Person objects to the array:

values.append(Person(name: "Peter" as! String, city: "Paris" as! String, country: "France" as! String))
values.append(Person(name: "Andrew" as! String, city: "Madrid" as! String, country: "Spain" as! String))

I would like to retrieve each of the attributes of each object of the array.

If I want to retrieve all the attributes of the first element I can do:

values[0].name
values[0].city
values[0].country

but I would like to do it in the way:

let totalAttributes = attributes.count - 1
for i in 0...totalAttributes{
   var attribute = attributes[i]
   values[0].attribute
}

but this, as I supposed, did not work.

In this case I can do it manually because there are only three attributes but I will not like to do the same when I will have more than 20 attributes inside the object.

Is there a way to do it within a loop?

Thanks in advance!

Upvotes: 3

Views: 158

Answers (3)

Benjamin Lowry
Benjamin Lowry

Reputation: 3789

If you add a function that returns the attributes of your Person class, then you should be able to do what you want. How you would process these values is another story. Below is an example of how you would change your Person class:

class Person{
    var name: String
    var city: String
    var country: String

    init(name: String, city: String, country: String){
        self.name = name
        self.city = city
        self.country = country
    }

    func returnAttributes() -> [AnyObject]{
        return [name, city, country]
    }
}

With your current scenario, you could also have the return type be [String], but it sounds like you are looking for a solution that allows for flexibility in terms of what types of objects its returning, so perhaps [AnyObject] is best.

So then you could do something like this:

let totalAttributes = attributes.count - 1
for i in 0...totalAttributes{
    values[0].returnAttributes //returns (for example): ["Peter", "Paris", "France"]
}

Upvotes: 0

Carien van Zyl
Carien van Zyl

Reputation: 2873

You can make use of reflection and MirrorType

let firstObj = values[0]
let personMirror = Mirror(reflecting: firstObj)
for child in personMirror.children {
    let (propertyName, propertyValue) = child
    print(propertyName)
    print(propertyValue)
}

You can access a specific property by the property name.

Example: Get the value of property named name

personMirror.descendant("name")

Upvotes: 2

zisoft
zisoft

Reputation: 23078

Let your class inherit from NSObject, then you can get/set its properties by the provided methods:

class Person: NSObject {
    var name: String
    var city: String
    var country: String

    init(name: String, city: String, country: String){
        self.name = name
        self.city = city
        self.country = country
    }
}

Now you can use:

var person = Person(...)
...
person.setValue("Peter", forKey: "name")
...
let name = person.value(forKey: "name")

Upvotes: 2

Related Questions