piaChai
piaChai

Reputation: 1571

How to determine the type of a variable in Swift

Is there a function to determine the variable type in Swift? I presume there might be something like like type() in Python.

I'd like a way to judge if a variable is a Foundation object or C variable in Swift. Like NSString vs String, or NSArray vs array. So that I can log it out in console and see clearly what it is.

For example, I would like to know the type inferred for the the first array below:

var array = [1,2,3]  // by default NSArray or array?
var array:[Int] = [1,2,3]
var array:NSArray = [1,2,3]
var array:Array<Any> = [1,2,3]

I have seen answers for judging if a given variable is a kind of given type in this question, but I'll say it's quite different from what I want to ask.

Upvotes: 38

Views: 33431

Answers (5)

James Shapiro
James Shapiro

Reputation: 6196

Someone mentioned this above, but I think it deserves visibility as an answer rather than a comment. You can now simply use type(of: ___):

var red, green, blue: Double
print(type(of: green))

yields

Double

Upvotes: 9

You can get a reference to the type object of a value by using the .dynamicType property. This is equivalent to Python's type() function, and is mentioned in the Swift documentation under Language Reference: Types: Metatype Type.

var intArray = [1, 2, 3]
let typeOfArray = intArray.dynamicType

With this type object, we are able to create a new instance of the same array type.

var newArray = typeOfArray()
newArray.append(5)
newArray.append(6)
println(newArray)
[5, 6]

We can see that this new value is of the same type ([Int]) by attempting to append a float:

newArray.append(1.5)
error: type 'Int' does not conform to protocol 'FloatLiteralConvertible'

If we import Cocoa and use an array literal with mixed types, we can see that an NSArray is created:

import Cocoa

var mixedArray = [1, "2"]
let mixedArrayType = mixedArray.dynamicType

var newArray = mixedArrayType()
var mutableArray = newArray.mutableCopy() as NSMutableArray

mutableArray.addObject(1)
mutableArray.addObject(1.5)
mutableArray.addObject("2")

println(mutableArray)
(1, "1.5", 2)

However, at this point there does not seem to be any general way to generate a string description of a type object, so this may not serve the debugging role that you were asking about.

Types derived from NSObject do have a .description() method, as is used in SiLo's answer,

println(mixedArrayType.description())
__NSArrayI

However this is not present on types such as Swift's built-in arrays.

println(typeOfArray.description())
error: '[Int].Type' does not have a member named 'description'

Upvotes: 26

piaChai
piaChai

Reputation: 1571

option+click the variable you'd like to examine.

enter image description here

Upvotes: 24

Snymax
Snymax

Reputation: 357

I use breakpoints during debuging but if you need to check if they match a certain type during runtime then drewag is right

another thing you can do is test datatype with assertion this would only work in debugging but with assertion you can set conditions which if met app crashes

maybe something like assert(let tArray == oldArray as? NSArray[] //if not NSArray app crashes)

Upvotes: 0

Erik
Erik

Reputation: 12858

It is possible to do so, though it's not necessarily that easy nor useful:

func getClassName(obj : AnyObject) -> String
{
    let objectClass : AnyClass! = object_getClass(obj)
    let className = objectClass.description()

    return className
}

let swiftArray = [1, 2, 3]
let swiftDictionary = ["Name": "John Doe"]
let cocoaArray : NSArray = [10, 20, 30]
var mutableCocoaArray = NSMutableArray()

println(getClassName(swiftArray))
println(getClassName(swiftDictionary))
println(getClassName(cocoaArray))
println(getClassName(mutableCocoaArray))

Output:

_TtCSs22ContiguousArrayStorage00007F88D052EF58
__NSDictionaryM
__NSArrayI
__NSArrayM

You are better of using the is and as keywords in Swift. Many foundation classes use class clusters (as you can see with __NSArrayI (immutable) and __NSArrayM (mutable).

Notice the interesting behavior. The swiftArray defaults to using a Swift Array<Int> while the swiftDictionary defaulted to NSMutableDictionary. With this kind of behavior I would not really rely on anything being a certain type (check first).

Upvotes: 10

Related Questions