38

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.

Community
  • 1
  • 1
piaChai
  • 1,551
  • 2
  • 15
  • 18
  • Not that I know of , but you can roll down your own? – Ali Gajani Jun 07 '14 at 03:51
  • I have edited question to make my statement more clear – piaChai Jun 07 '14 at 04:04
  • Could you give an example of the type of code where you'd like to use this knowledge? If the type is known at compile-time, you could probably use a generic function, something like `func show(x:T) { println("\(x) is of type \(T)" }`. If it's not known as at compile-time, I'm not sure if this would even be possible, since it doesn't seem like a C value would have the necessary runtime metadata. (Sadly I can't try this for myself because Apple still hasn't approved my developer account.) – Jeremy Jun 07 '14 at 04:12
  • 1
    I do not agree with closing this question as a duplicate of [How to get Type of an Object in Swift](http://stackoverflow.com/q/24091882/1114). Even though the question as written would be an appropriate duplicate, the reality is that all of the answers, *including the accepted answer*, only address determining whether a value is of a given type. Unless the asker of that other question wants to un-accept that answer, I think it's only reasonable that they narrow the question to be about checking if a value is of a given type, making it distinct from this question. – Jeremy Jun 07 '14 at 04:53
  • I agree,determine a given type and determine the type directly are just not the same – piaChai Jun 07 '14 at 05:17
  • I have edited this question to disambiguate it from http://stackoverflow.com/q/24091882 and am voting to reopen. They are both useful, similar, questions, but the answers are quite distinct so it would be useful to keep them separated. – Jeremy Jun 07 '14 at 17:45

5 Answers5

26

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'
Community
  • 1
  • 1
Jeremy
  • 1
  • 85
  • 340
  • 366
  • BTW: instead of `obj.description()`, you can always use `String(obj)` (this will use the description if it is available). – Tali Sep 11 '15 at 11:03
  • 5
    .dynamicType is deprecated now. typeof equivalent is now type(of: myvariable) – xiay Sep 22 '16 at 07:04
  • @logicor Thanks for the info. Want to suggest an edit to this post (so you'll get credit for the addition)? If not, I'll edit it in myself later. – Jeremy Sep 22 '16 at 17:57
23

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

enter image description here

piaChai
  • 1,551
  • 2
  • 15
  • 18
10

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).

Erik
  • 12,730
  • 5
  • 36
  • 42
9

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

James Shapiro
  • 4,805
  • 3
  • 31
  • 46
0

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)

Snymax
  • 357
  • 4
  • 18
  • This checks _if_ a var is of a _specific_ type, not _what_ type it _is_. Thanks for your input. –  Oct 15 '17 at 13:06