18

How can Ioop through an NSMutableArray in Swift? What I have tried:

var vehicles = NSMutableArray()

The array contains objects from class: Vehicle

for vehicle in vehicles {
    println(vehicle.registration)
}

I cannot run the above code without the compiler telling me registration doesn't belong to AnyObject. At this point I assumed that was because I hadn't told the for loop what type of class item belongs to. So I modified by code:

for vehicle: Vehicle in vehicles {
    println(vehicle.registration)
}

Now the compiler complains about downcasting... how can I simply gain access to the custom registration property whilst looping through the array of Vehicles?

jskidd3
  • 4,609
  • 15
  • 63
  • 127

3 Answers3

31

This should work:

for vehicle in (vehicles as NSArray as! [Vehicle]) {
    println(vehicle.registration) 
}
dnnagy
  • 3,711
  • 4
  • 24
  • 34
17

As Romain suggested, you can use Swift array. If you continue to use NSMutableArray, you could do either:

for object in vehicles {
    if let vehicle = object as? Vehicle {
        print(vehicle.registration)
    }
}

or, you can force unwrap it, using a where qualifier to protect yourself against cast failures:

for vehicle in vehicles where vehicle is Vehicle {
    print((vehicle as! Vehicle).registration)
}

or, you can use functional patterns:

vehicles.compactMap { $0 as? Vehicle }
    .forEach { vehicle in
        print(vehicle.registration)
}

Obviously, if possible, the question is whether you can retire NSMutableArray and use Array<Vehicle> (aka [Vehicle]) instead. So, instead of:

let vehicles = NSMutableArray()

You can do:

var vehicles: [Vehicle] = []

Then, you can do things like:

for vehicle in vehicles {
    print(vehicle.registration)
}

Sometimes we're stuck with Objective-C code that's returning NSMutableArray objects, but if this NSMutableArray was created in Swift, it's probably preferable to use Array<Vehicle> instead.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
4

NSMutableArray comes from the Objective-C world. Now you can use generics and strongly-typed arrays, like this:

var vehicles = [Vehicle]()
...
for vehicle in vehicles {
    println(vehicle.registration)
}
Romain
  • 3,718
  • 3
  • 32
  • 48
  • Thanks for your answer! Would I be able to use the `removeObjectsAtIndexes` method on your `vehicles` array? I am converting an NSArray to an array that allows me to use that for technical reasons in my app... as long that works your answer is perfect – jskidd3 Feb 08 '15 at 13:10
  • Sure. Swift arrays don't provide this method natively, but you can code your own without much trouble: http://stackoverflow.com/questions/26173565/removeobjectsatindexes-for-swift-arrays (see the answer that has most upvotes, it is not the accepted one but most valid one) – Romain Feb 08 '15 at 13:16