Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can an [AnyObject] array be optionally downcast to a type-specific array?

I'm reading through the Swift documentation, looking at the section regarding type casting.

The documentation talks about getting an array of type [AnyObject] from Foundation frameworks stuff (what would be an NSArray * in Objective-C).

First, the documentation provides this example:

for object in someObjects {     let movie = object as Movie     println("Movie: '\(movie.name)', dir. \(movie.director)") } 

Now, I want to change the example slightly, to a case where I don't know all the objects are of type Movie, so I'd do this:

for object in someObject {     if let movie = object as? Movie {         println("Movie: '\(movie.name', dir. \(movie.director)")     } } 

The documentation then provides an example of a better way to write the first loop:

for movie in someObjects as [Movie] {    println("Movie: '\(movie.name)', dir. \(movie.director)") } 

Where we downcast someObjects from an [AnyObject] to a [Movie] so we don't have to downcast within the loop.

And this got me thinking, can the array be option downcast as a whole?

if let someMovies = someObjects as? [Movie] {     for movie in someMovies {         println("Movie: '\(movie.name)', dir. \(movie.director)")     } } 

Does this work? And if so, how bad is this from a performance standpoint? How long would it take to check the type of every object in a 10,000 element array using the optional downcast?

I understand that the implications between this snippet and my previous optional downcast snippet are different. The first will iterate through every object and only attempt to print if the object is a Movie, where the second will only enter the loop if the array can be downcast to a [Movie] array, in which case it will either print all or none, but I can imagine there are situations where this would be preferable.

like image 528
nhgrif Avatar asked Jun 05 '14 02:06

nhgrif


People also ask

Which of the following operator is used for Downcasting the subclass type with a type cast operator?

Downcasting. A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. Where you believe this is the case, you can try to downcast to the subclass type with a type cast operator ( as? or as! ).

What is the difference between Upcast and downcast in Swift?

Downcasting is the opposite of upcasting, and it refers to casting an object of a parent class type to an object of its children class. Downcasting is used to reconvert objects of a children class that were upcasted earlier to generalize.

What is type casting in Swift explain with example?

To validate the type of an instance 'Type Casting' comes into play in Swift 4 language. It is used to check whether the instance type belongs to a particular super class or subclass or it is defined in its own hierarchy.

What is as in Swift?

Operator. Prior to Swift 1.2, the as operator could be used to carry out two different kinds of conversion, depending on the type of expression being converted and the type it was being converted to: Guaranteed conversion of a value of one type to another, whose success can be verified by the Swift compiler.


2 Answers

You've got it -- it works exactly like your example code:

let strings = ["Hi", "Hello", "Aloha"] let anyObjects: [AnyObject] = strings  if let downcastStrings = anyObjects as? [String] {     println("It's a [String]") } // console says "It's a [String]" 

No idea about performance, but I wouldn't assume that it will have to iterate through the full array to determine if a downcast is possible.


So I got curious, and ran a quick test with 100,000 simple values in a couple different [AnyObject] configurations, where I'm trying to downcast the array to a [String] vs. downcasting the individual elements:

// var anyObjects: [AnyObject] = [AnyObject]() // filled with random assortment of Int, String, Double, Bool Running test with mixed array downcast array execution time = 0.000522 downcast elements execution time = 0.571749  // var actuallyStrings: [AnyObject] = [AnyObject]() // filled with String values Running test with all strings downcast array execution time = 1.141267 downcast elements execution time = 0.853765 

It looks like it's super fast to dismiss the mixed array as non-downcastable, since it just needs to scan until it finds a non-String element. For an array that it can downcast, it clearly has to crunch through the whole array, and takes much longer, although I'm not sure why it's not the same speed as looping through the array and manually checking each element.

like image 105
Nate Cook Avatar answered Sep 27 '22 15:09

Nate Cook


Let's try this

var someObjects = [     NSString(),     NSUUID() ] let uuids = someObjects as? NSUUID[] 

uuids is nil

var someOtherObjects = [     NSUUID(),     NSUUID() ] let all_uuids = someOtherObjects as? NSUUID[] 

all_uuids is equal to someOtherObjects

So it looks like it does work. You can use the expression to test if all elements of the array are of the expected type but it will not filter the array to select only the expected type.

like image 25
Rod Avatar answered Sep 27 '22 16:09

Rod