1

I have an array of AnyObject type like this: [[String : AnyObject]]

animalList = [["name": ABC, "color":red], ["name": DEF, "color": green], ["name": GHI, "color": blue ]]

The model class is like this:

class ModelAnimal {

    var name: String
    var color: String

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

How can I put them in an array of ModelAnimal type:

var myList = Array<ModelAnimal>()

    for var i = 0; i < animalList.count; i++ {

     myList.

    }
1
  • This code doesn't compile as-is. Are the values ABC and the colors like red Strings? Commented Nov 25, 2015 at 17:01

4 Answers 4

5

Use map to create a new array of type [ModelAnimal]:

let animalList: [[String: AnyObject]] = [["name": "ABC", "color":"red"], ["name": "DEF", "color": "green"], ["name": "GHI", "color": "blue"]]

class ModelAnimal {

    var name: String
    var color: String

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

let myList = animalList.map { ModelAnimal(name: $0["name"] as? String ?? "", color: $0["color"] as? String ?? "") }

This also makes use of conditional cast as? String along with the nil coalescing operator ?? to safely extract the values from the array of dictionaries and pass them to the constructor for ModelAnimal.

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

Comments

3

1. Struct

First suggestion, use a Struct instead of a Class the model.

Why a Struct?

  1. A Struct does allow you to define a failable init that can return fail without initialising all the stored properties.
  2. A Struct is saved into the Stack Memory of your device that is much faster then the heap.
  3. Finally if the name and color field are not going to change you should really declare them as let. This way you Struct is going to be totally immutable (that is good for several reasons).

2. Failable initializer

Add a failable inititializer to your model that receives optional params

struct ModelAnimal {

    let name: String // you can change this back to var if needed
    let color: String  // you can change this back to var if needed

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

    init?(name: String?, color: String?) {
        guard let name = name, color = color else { return nil }
        self.name = name
        self.color = color
    }
}

3. flatMap

Now you can use the powerful flapMap function

let animals = animalList.flatMap { ModelAnimal(name: $0["name"], color: $0["color"]) }

Why flatMap?

  1. The beauty of flatMap is that it does returns only non nil values. Infact animalList contains unstructured data and you have no guarantee (at least at compile time) that each element has a name and a color key. This way if bad data is contained into animalList it is simply discarded.
  2. Another advantage of flatMap is that it does return an array of ModelAnimal, not ModelAnimal?.

4 Comments

Nice! You are going to need a cast to deal with the fact that the values in the dictionary are AnyObject.
I didn't think you could have a failable initializer with the same signature as a non-failable one.
@MikeAtNobel: actually the 2 initialisers don't have the same signature. String and String? are different types.
Fair enough. I guess that is enough information for the compiler to decide which initializer to use. +1
0

The code just iterates over animalList and adds new items to myList:

var myList = Array<ModelAnimal>()

for var i = 0; i < animalList.count; i++ {
    myList.append(ModelAnimal(name: animalList[i]["name"]!, color: animalList[i]["color"]!))
}

It works, however calling append every time isn't good for performance. Better way to achieve this is to create array with needed length:

for var i = 0; i < animalList.count; i++ {
    myList[i] = ModelAnimal(name: animalList[i]["name"]!, color: animalList[i]["color"]!)
}

Comments

0

First initialize your ModelAnimal objects, then add them to an array:

let animalOne = ModelAnimal(name: "ABC", color: "red")
let animalTwo = ModelAnimal(name: "DEF", color: "green")
let animalThree = ModelAnimal(name: "GHI", color: "blue")

let myList: Array<ModelAnimal> = [animalOne, animalTwo, animalThree]

You could also do this in-line:

let myList: Array<ModelAnimal> = [ModelAnimal(name: "ABC", color: "red"), ModelAnimal(name: "DEF", color: "green"), ModelAnimal(name: "GHI", color: "blue")]

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.