user4938361
user4938361

Reputation: 149

Skip over null arrays in Swift?

Sorry, I wasn't quite sure how to phrase the question. So I know exactly what the problem is. I am reading from several plists. Some of the plists have no Array stored in "evolved_species_id", which gives the error

Index out of range

How do I get my code to skip over the instances of "evolved_species_id" that have no stored array? This is the code I'm using to grab the data.

convenience init(fromDict dict: [String:Any]) {
    let ef = dict["evolves-from"] as? [[String:Any]]
    let ef1 = ef?[0]["evolved_species_id"]
    self.init(
        prevo: ef1 as? Int ?? 0,
    )

}

It never gets to the self.init line because the console error is created at let ef1 = ef?[0]["evolved_species_id"]

Upvotes: 1

Views: 415

Answers (5)

Midhun MP
Midhun MP

Reputation: 107211

You should always check whether the array contains anything before indexing it, it will avoid index out of bound exceptions. Since you are trying to get the 0th index element you can re-write your code using first property of array:

init(fromDict dict: [String:Any])
{
    let ef = dict["evolves-from"] as? [[String:Any]]
    let ef1 = ef?.first?["evolved_species_id"]
    self.init(prevo: ef1 as? Int ?? 0)
}

Use the first and last properties for safe access to the value of the array’s first and last elements. If the array is empty, these properties are nil.

Swift Array Reference

Upvotes: 0

vadian
vadian

Reputation: 285180

You could check if the array exists and is not empty

convenience init(fromDict dict: [String:Any]) {
    let ef1 : Int
    if let ef = dict["evolves-from"] as? [[String:Any]], !ef.isEmpty {
        ef1 = ef[0]["evolved_species_id"] as! Int
    } else {
        ef1 = 0
    }
    self.init(
        prevo = ef1 // the colon syntax won't compile most likely.
    )
}

or use a failable initializer

convenience init?(fromDict dict: [String:Any]) {

    guard let ef = dict["evolves-from"] as? [[String:Any]], !ef.isEmpty else {
       return nil
    }

    self.init(
        prevo = ef[0]["evolved_species_id"] as! Int
    )
}

Upvotes: 1

Usman Javed
Usman Javed

Reputation: 2455

You can do something like this

convenience init(fromDict dict: [String:Any]) {
    let ef = dict["evolves-from"] as? [[String:Any]]
    if !(ef.isEmpty){ /// OR if (ef.count > 0) 
        let ef1 = ef?[0]["evolved_species_id"]
    self.init(
        prevo: ef1 as? Int ?? 0,
    )
  }
 }

Upvotes: 0

Sahil
Sahil

Reputation: 9226

You can use if let construct for safely unwrap and check array elements is greater than zero using where.

if let ef = dict["evolves-from"] as? [[String:Any]] where ef.count > 0 {
let ef1 = ef[0]["evolved_species_id"]
self.init(
    prevo: ef1 as? Int ?? 0,
 )
} else {
 self.init(
    prevo: 0 
)
}

and if you're using Swift 3.0

if let ef = dict["evolves-from"] as? [[String:Any]], ef.count > 0 {
 let ef1 = ef[0]["evolved_species_id"]
  self.init(
    prevo: ef1 as? Int ?? 0,
   )
 } else {
   self.init(
    prevo: 0 
   )
 }

Upvotes: 0

Lombas
Lombas

Reputation: 1132

Try using if let instead of just let. This may avoid the error.

Upvotes: 0

Related Questions