Vas Vas - 4 months ago 19
Swift Question

Wrong number casting in Swift

The following code give me the answer "float".

let z : AnyObject = Int(2)

if z is Float {
print("float")
} else {
print("int")
}


Is it correct?

I'm using Xcode 7.3.1.

Answer

In pure Swift, this line:

let z: AnyObject = Int(2)

gives error: value of type 'Int' does not conform to specified type 'AnyObject'

That is because AnyObject holds objects (instances of classes), but it doesn't hold structs or primitive types.

When Foundation is imported (through import UIKit, import Cocoa, or import Foundation), Swift will convert Int, Float, Double, and Bool into an NSNumber. You can see that this is true by printing:

print(z.dynamicType)
__NSCFNumber

That is the internal representation of NSNumber.

NSNumber is an object which wraps primitive types. It is used in Objective-C to store these values in an NSArray which holds AnyObjects.

The interesting thing about NSNumber is that you can put in all of those types (Int, Double, Float, Bool) and then take the value out as any of those types. Consider:

let z: AnyObject = 3.14

print(z as! Int)     // 3
print(z as! Float)   // 3.14
print(z as! Bool)    // true

So, when you query an NSNumber with is Int, is Float, is Double, or is Bool, it will always return true meaning "I can be that type if you want".


Using Any instead of AnyObject

If instead, you use Any, then you'll get the expected result:

let z: Any = 2

if z is Float {
    print("float")
} else {
    print("int")    // prints "int"
}

That is because Any can store any type, not just instances of classes, so the underlying type remains an Int:

print(z.dynamicType)
Int

Why does Swift convert Ints to NSNumber when assigned to AnyObject?

This is done to make working with Objective-C based frameworks such as Cocoa and Cocoa Touch easier. It enables you to pass an array such as [2, 3.14, "hello"] into a function that expects an NSArray. This is certainly easier to use than NSArray(arrayLiteral: NSNumber(integer: 2), NSNumber(float: 3.14), NSString(string: "hello")).

Comments