Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A double number's type is Int in Swift

Tags:

swift

// Swift
import UIKit
let arr = [1, "a", 2.88]
let last = arr.last
if last is Int {
    print("The last is Int.")    // The last is Int.
} else {
    print("The last is not Int.")
}

I can't understand the result printed.
Why it print "The last is Int".

// Swift
import UIKit
let arr = [1, "a", -2]
let last = arr.last
if last is Double {
    print("The last is Double.")    // The last is Double.
} else {
    print("The last is not Double.")
}

And this print "The last is Double".Why?
Could somebody can help me?
Than you vary much.

like image 832
ErYe Avatar asked Dec 24 '22 06:12

ErYe


1 Answers

Swift arrays can only hold one type. When you declared:

let arr = [1, "a", 2.88]

Swift made arr of type [NSObject]. You can verify this by Option-clicking on arr to see its type. This only works because you have Foundation imported (your import UIKit imports Foundation as well). Try removing import UIKit.

Then, the values 1 and 2.88 were converted to NSNumber and "a" to NSString so that they can be stored in that [NSObject] array because Ints, Strings, and Doubles are not NSObjects. NSNumber and NSString are subclasses of NSObject. Swift picks the most restrictive type for the array. Had your array been [1, true, 2.88], the array type would have been [NSNumber].

The interesting thing about an NSNumber is that it is an object container that wraps many different types. You can put an Int in and take out a Double. So, it is misleading then when you test it with is. It responds "true" meaning, "I can be that if you want".


import Foundation

let n: NSNumber = 3.14

print(n is Int)       // "true"
print(n is Double)    // "true"
print(n is Bool)      // "true"

print(n as! Int)      // "3"
print(n as! Double)   // "3.14"
print(n as! Bool)     // "true"

Note: Had you declared your arr to be [Any], then this would have worked as you expected:

let arr:[Any] = [1, "a", 2.88]
let last = arr.last
if last is Int {
    print("The last is Int.")
} else {
    print("The last is not Int.")  // "The last is not Int."
}

But Swift is not going to create an array of type Any for you unless you ask explicitly (because quite frankly it is an abomination in a strongly typed language). You should probably rethink your design if you find yourself using [Any].

The only reason Swift creates [NSObject] when Foundation is imported is to make our lives easier when calling Cocoa and Cocoa Touch APIs. If such an API requires an NSArray to be passed, you can send [1, "a", 2.88] instead of [NSNumber(integer: 1), NSString(string: "a"), NSNumber(double: 2.88)].

like image 198
vacawama Avatar answered Mar 08 '23 04:03

vacawama