Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift type inference and type checking issue

I'm not looking for an answer like how to do it correctly but why this happens.

Here is the code:

func isInt(param: AnyObject?) {
    if let value = param as? Int {
        print(value)
    } else {
        print("Not Int")
    }

    if let value = param {
        if value is Int {
            print(value)
        } else {
            print("Not Int")
        }
    }
}

let a:AnyObject? = 1.2
let b:Float? = 1.2
let c:Double? = 1.2

isInt(a)
isInt(b)
isInt(c)

I understand in the first if loop, the param is casted to Int and then print out 1.

But why in second if loop, if value is Int is true and then print out 1.2?

like image 843
Breek Avatar asked Feb 08 '23 21:02

Breek


1 Answers

Take a look at https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html, specifically:

Instances of the Swift numeric structure types, such as Int, UInt, Float, Double, and Bool, cannot be represented by the AnyObject type, because AnyObject only represents instances of a class type. However, when bridging to Foundation is enabled, Swift numeric values can be assigned to constants and variables of AnyObject type as bridged instances of the NSNumber class.

We can see this in action in a Playground:

let value = 1.2
value.dynamicType                   //Double.Type
value is Int                        //false
let castValue = value as AnyObject
castValue.dynamicType               //__NSCFNumber.Type (a private framework class, part of the NSNumber class cluster)
//NSNumber is bridged to Int, UInt, Float, Double, and Bool so `is` tests for those types will return `true`
castValue is Int                    //true
castValue is Float                  //true
//NSNumber is not bridged to String so an `is` test will return `false`
castValue is String                 //false
like image 83
Jonah Avatar answered Feb 15 '23 07:02

Jonah