How do I print the type or class of a variable in Swift?
Asked Answered
S

34

365

Is there a way to print the runtime type of a variable in swift? For example:

var now = NSDate()
var soon = now.dateByAddingTimeInterval(5.0)

println("\(now.dynamicType)") 
// Prints "(Metatype)"

println("\(now.dynamicType.description()")
// Prints "__NSDate" since objective-c Class objects have a "description" selector

println("\(soon.dynamicType.description()")
// Compile-time error since ImplicitlyUnwrappedOptional<NSDate> has no "description" method

In the example above, I'm looking for a way to show that the variable "soon" is of type ImplicitlyUnwrappedOptional<NSDate>, or at least NSDate!.

Squish answered 3/6, 2014 at 2:24 Comment(5)
@JasonMArcher Tell me how is this a duplicate if the question you linked was asked 4 days after this one?Omniscience
There are a number of questions about testing the type of a Swift object or reading the type of a Swift object. We are just finding the best questions to use as the "master" questions for this subject. The suggested duplicate has a much more thorough answer. This isn't to say that you did something wrong, just that we are trying to reduce the clutter.Rusticate
The suggested duplicate is not answering the same question; Type.self cannot be printed to the console for the purposes of debugging, it is meant to be used to pass to other functions that take Types as objects.Squish
OT: Very strange that Swift does not offer that out of the box and one needs to fiddle around with such low level C libraries. Worth a bug report?Insentient
Guys, I have provided my answer below. Please have a look and let me know if that is what is expected.Bookstand
C
407

Update September 2016

Swift 3.0: Use type(of:), e.g. type(of: someThing) (since the dynamicType keyword has been removed)

Update October 2015:

I updated the examples below to the new Swift 2.0 syntax (e.g. println was replaced with print, toString() is now String()).

From the Xcode 6.3 release notes:

@nschum points out in the comments that the Xcode 6.3 release notes show another way:

Type values now print as the full demangled type name when used with println or string interpolation.

import Foundation

class PureSwiftClass { }

var myvar0 = NSString() // Objective-C class
var myvar1 = PureSwiftClass()
var myvar2 = 42
var myvar3 = "Hans"

print( "String(myvar0.dynamicType) -> \(myvar0.dynamicType)")
print( "String(myvar1.dynamicType) -> \(myvar1.dynamicType)")
print( "String(myvar2.dynamicType) -> \(myvar2.dynamicType)")
print( "String(myvar3.dynamicType) -> \(myvar3.dynamicType)")

print( "String(Int.self)           -> \(Int.self)")
print( "String((Int?).self         -> \((Int?).self)")
print( "String(NSString.self)      -> \(NSString.self)")
print( "String(Array<String>.self) -> \(Array<String>.self)")

Which outputs:

String(myvar0.dynamicType) -> __NSCFConstantString
String(myvar1.dynamicType) -> PureSwiftClass
String(myvar2.dynamicType) -> Int
String(myvar3.dynamicType) -> String
String(Int.self)           -> Int
String((Int?).self         -> Optional<Int>
String(NSString.self)      -> NSString
String(Array<String>.self) -> Array<String>

Update for Xcode 6.3:

You can use the _stdlib_getDemangledTypeName():

print( "TypeName0 = \(_stdlib_getDemangledTypeName(myvar0))")
print( "TypeName1 = \(_stdlib_getDemangledTypeName(myvar1))")
print( "TypeName2 = \(_stdlib_getDemangledTypeName(myvar2))")
print( "TypeName3 = \(_stdlib_getDemangledTypeName(myvar3))")

and get this as output:

TypeName0 = NSString
TypeName1 = __lldb_expr_26.PureSwiftClass
TypeName2 = Swift.Int
TypeName3 = Swift.String

Original answer:

Prior to Xcode 6.3 _stdlib_getTypeName got the mangled type name of a variable. Ewan Swick's blog entry helps to decipher these strings:

e.g. _TtSi stands for Swift's internal Int type.

Mike Ash has a great blog entry covering the same topic.

Chutney answered 17/8, 2014 at 1:18 Comment(13)
How did you find _stdlib_getTypeName()? The integrated REPL no longer exists, swift-ide-test doesn't exist either, and Xcode's printing of the Swift module elides _-prefixed values.Delk
Looks like I can search symbols with lldb easily enough in the repl. There's also _stdlib_getDemangledTypeName(), and _stdlib_demangleName().Delk
I first saw it in a symbol dump gist on github. I can't reconstruct which one exactly because there were so many. But you are right, a simple (lldb) image dump symtab libswiftCore.dylib yields the same result. BTW: Great catch with _stdlib_demangleName()!Chutney
Oh neat, I didn't realize image was a shortcut for target modules. I ended up using target modules lookup -r -n _stdlib_, which of course is better-expressed as image lookup -r -n _stdlib_ libswiftCore.dylibDelk
Thanks Kevin Ballard. _stdlib_getDemangledTypeName() worked best for me.Sclater
Just to elaborate on what has already been said, using _stdlib_getDemangledTypeName() and extracting the last component appears to work for all classes and primitives. e.g.: println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!)Eam
I just would like to do an update, looks that on Xcode 6.3 _stdlib_getTypeName and _stdlib_demangleName have gone, the only one that is still working for me is _stdlib_getDemangledTypeName.Finn
The Xcode 6.3 release notes say to use toString to get demangled names. _stdlib_getDemangledTypeName does the same thing but will probably break sooner or later.Stalinabad
FYI - Looks like toString(...) has been replaced with String(...).Universalize
I think there is no need to add .self in class. For example: String(NSUserDefaults) prints the same as String(NSUserDefaults.self)Historic
Swift 3.0: The dynamicType keyword has been removed from Swift. In its place a new primitive function type(of:) has been added to the language: github.com/apple/swift/blob/master/CHANGELOG.mdLowder
This answer is deprecated. Use type(of:) instead.Barsky
Would be more helpful if all parts of answer referencing .dynamicType were removed from the accepted answer, since that call is now deprecated (at least in my Xcode 9.0)Alburnum
O
46

Edit: A new toString function has been introduced in Swift 1.2 (Xcode 6.3).

You can now print the demangled type of any type using .self and any instance using .dynamicType:

struct Box<T> {}

toString("foo".dynamicType)            // Swift.String
toString([1, 23, 456].dynamicType)     // Swift.Array<Swift.Int>
toString((7 as NSNumber).dynamicType)  // __NSCFNumber

toString((Bool?).self)                 // Swift.Optional<Swift.Bool>
toString(Box<SinkOf<Character>>.self)  // __lldb_expr_1.Box<Swift.SinkOf<Swift.Character>>
toString(NSStream.self)                // NSStream

Try calling YourClass.self and yourObject.dynamicType.

Reference: https://devforums.apple.com/thread/227425.

Omniscience answered 3/6, 2014 at 10:31 Comment(4)
I responded to that thread, but I'll add my comment here. Those values are of type "Metatype," but there doesn't appear to be an easy way to figure out what type a Metatype object represents, which is what I'm looking for.Squish
They are of type Metatype, and they are classes. They represent a class. Not sure exactly what your problem is with that. someInstance.dynamicType.printClassName() will print the name of the class.Taffy
the printClassName() method is just an example method they created in one of the samples in the docs, it is not an API call you can access.Darnell
FYI - Looks like toString(...) has been replaced with String(...)Universalize
S
40

Swift 3.0

let string = "Hello"
let stringArray = ["one", "two"]
let dictionary = ["key": 2]

print(type(of: string)) // "String"

// Get type name as a string
String(describing: type(of: string)) // "String"
String(describing: type(of: stringArray)) // "Array<String>"
String(describing: type(of: dictionary)) // "Dictionary<String, Int>"

// Get full type as a string
String(reflecting: type(of: string)) // "Swift.String"
String(reflecting: type(of: stringArray)) // "Swift.Array<Swift.String>"
String(reflecting: type(of: dictionary)) // "Swift.Dictionary<Swift.String, Swift.Int>"
Soporific answered 19/8, 2015 at 5:50 Comment(1)
The Swift 2 implementation is particularly nice with enum cases. Does anyone know whether this behaviour is documented/guaranteed by Apple? Standard library merely includes a comment that this is suitable for debugging...Reld
H
30

Is this what you're looking for?

println("\(object_getClassName(now))");

It prints "__NSDate"

UPDATE: Please note this no longer seems to work as of Beta05

Hightail answered 6/6, 2014 at 10:33 Comment(2)
Doesn't work for swift classes. Returns "UnsafePointer(0x7FBB18D06DE0)"Tal
Doesn't work for ObjC classes either (at least in Beta5), for an NSManagedObject I just get "Builtin.RawPointer = address"Farhi
T
23

My current Xcode is Version 6.0 (6A280e).

import Foundation

class Person { var name: String; init(name: String) { self.name = name }}
class Patient: Person {}
class Doctor: Person {}

var variables:[Any] = [
    5,
    7.5,
    true,
    "maple",
    Person(name:"Sarah"),
    Patient(name:"Pat"),
    Doctor(name:"Sandy")
]

for variable in variables {
    let typeLongName = _stdlib_getDemangledTypeName(variable)
    let tokens = split(typeLongName, { $0 == "." })
    if let typeName = tokens.last {
        println("Variable \(variable) is of Type \(typeName).")
    }
}

Output:

Variable 5 is of Type Int.
Variable 7.5 is of Type Double.
Variable true is of Type Bool.
Variable maple is of Type String.
Variable Swift001.Person is of Type Person.
Variable Swift001.Patient is of Type Patient.
Variable Swift001.Doctor is of Type Doctor.
Teakwood answered 8/9, 2014 at 17:45 Comment(1)
Good, but the question also included Optionals, output of optionals are set in Optional(...), so your code would only return Optional as the Type. It should also show var optionalTestVar: Person? = Person(name:"Sarah") as Optional(Person) and var with Person! as ImplicitlyUnwrappedOptional(Person)Sere
A
18

As of Xcode 6.3 with Swift 1.2, you can simply convert type values into the full demangled String.

toString(Int)                   // "Swift.Int"
toString(Int.Type)              // "Swift.Int.Type"
toString((10).dynamicType)      // "Swift.Int"
println(Bool.self)              // "Swift.Bool"
println([UTF8].self)            // "Swift.Array<Swift.UTF8>"
println((Int, String).self)     // "(Swift.Int, Swift.String)"
println((String?()).dynamicType)// "Swift.Optional<Swift.String>"
println(NSDate)                 // "NSDate"
println(NSDate.Type)            // "NSDate.Type"
println(WKWebView)              // "WKWebView"
toString(MyClass)               // "[Module Name].MyClass"
toString(MyClass().dynamicType) // "[Module Name].MyClass"
Ahrens answered 10/2, 2015 at 4:37 Comment(2)
Is the other direction possible in 1.2? To initialise an instance based on the class name?Inaptitude
@Inaptitude As far as I know I don't think there is any.Ahrens
C
17

You can still access the class, through className (which returns a String).

There are actually several ways to get the class, for example classForArchiver, classForCoder, classForKeyedArchiver (all return AnyClass!).

You can't get the type of a primitive (a primitive is not a class).

Example:

var ivar = [:]
ivar.className // __NSDictionaryI

var i = 1
i.className // error: 'Int' does not have a member named 'className'

If you want to get the type of a primitive, you have to use bridgeToObjectiveC(). Example:

var i = 1
i.bridgeToObjectiveC().className // __NSCFNumber
Cheesewood answered 3/6, 2014 at 2:30 Comment(7)
I bet it's a primitive. Unfortunately you can't get the type of a primitive.Cheesewood
Those examples don't seem to work in the playground. I get the error for primitives and non-primitives alike.Squish
try to import Cocoa.Cheesewood
"No such module 'Cocoa'"Squish
Can you copy/paste your entire working playground here, including import statements? Could you show how to print "NSDate" from the variable "now" in my example using className?Squish
className appears to be only available for NSObjects when developing for OSX; it's not available in the iOS SDK for either NSObjects or "normal" objectsSquish
className is part of Cocoa's AppleScript support and should definitely not be used for generic introspection. Obviously it's not available on iOS.Vlissingen
D
16

You can use reflect to get information about object.
For example name of object class:

var classname = reflect(now).summary
Drinking answered 15/8, 2014 at 12:27 Comment(2)
In Beta 6, this got me the app name + class name in a slightly mangled form, but it's a start. +1 for reflect(x).summary -- thanks!Crassulaceous
did not work, prints a blank line in Swift 1.2 Xcode 6.4 and iOs 8.4Schlesien
A
15

Xcode 8 Swift 3.0 use type(of:)

let className = "\(type(of: instance))"
Abbieabbot answered 19/9, 2016 at 19:10 Comment(0)
O
13

I had luck with:

let className = NSStringFromClass(obj.dynamicType)
Oglethorpe answered 7/9, 2014 at 20:58 Comment(1)
@hdost dude nothing worked but classForCoder worked.Jehovist
C
12

SWIFT 5

With the latest release of Swift 3 we can get pretty descriptions of type names through the String initializer. Like, for example print(String(describing: type(of: object))). Where object can be an instance variable like array, a dictionary, an Int, a NSDate, an instance of a custom class, etc.

Here is my complete answer: Get class name of object as string in Swift

That question is looking for a way to getting the class name of an object as string but, also i proposed another way to getting the class name of a variable that isn't subclass of NSObject. Here it is:

class Utility{
    class func classNameAsString(obj: Any) -> String {
        //prints more readable results for dictionaries, arrays, Int, etc
        return String(describing: type(of: obj))
    }
}

I made a static function which takes as parameter an object of type Any and returns its class name as String :) .

I tested this function with some variables like:

    let diccionary: [String: CGFloat] = [:]
    let array: [Int] = []
    let numInt = 9
    let numFloat: CGFloat = 3.0
    let numDouble: Double = 1.0
    let classOne = ClassOne()
    let classTwo: ClassTwo? = ClassTwo()
    let now = NSDate()
    let lbl = UILabel()

and the output was:

  • diccionary is of type Dictionary
  • array is of type Array
  • numInt is of type Int
  • numFloat is of type CGFloat
  • numDouble is of type Double
  • classOne is of type: ClassOne
  • classTwo is of type: ClassTwo
  • now is of type: Date
  • lbl is of type: UILabel
Constrictor answered 15/2, 2015 at 0:45 Comment(0)
B
10

In Xcode 8, Swift 3.0

Steps:

1. Get the Type:

Option 1:

let type : Type = MyClass.self  //Determines Type from Class

Option 2:

let type : Type = type(of:self) //Determines Type from self

2. Convert Type to String:

let string : String = "\(type)" //String
Bonilla answered 9/10, 2016 at 12:13 Comment(0)
S
9

In Swift 3.0, you can use type(of:), as dynamicType keyword has been removed.

Steven answered 17/9, 2016 at 6:7 Comment(0)
S
7

To get a type of object or class of object in Swift, you must need to use a type(of: yourObject)

type(of: yourObject)

Shadwell answered 27/11, 2018 at 14:27 Comment(1)
Confiming that the same works for swift 5.4 versionPowdery
S
5

When using Cocoa (not CocoaTouch), you can use the className property for objects that are subclasses of NSObject.

println(now.className)

This property is not available for normal Swift objects, which aren't subclasses of NSObject (and in fact, there is no root id or object type in Swift).

class Person {
    var name: String?
}

var p = Person()
println(person.className) // <- Compiler error

In CocoaTouch, at this time there is not a way to get a string description of the type of a given variable. Similar functionality also does not exist for primitive types in either Cocoa or CocoaTouch.

The Swift REPL is able to print out a summary of values including its type, so it is possible this manner of introspection will be possible via an API in the future.

EDIT: dump(object) seems to do the trick.

Squish answered 4/6, 2014 at 13:48 Comment(1)
Even as of Xcode 10 and Swift 4.2, dump(object) is really powerful. Thank you.Mcgehee
B
5

The top answer doesn't have a working example of the new way of doing this using type(of:. So to help rookies like me, here is a working example, taken mostly from Apple's docs here - https://developer.apple.com/documentation/swift/2885064-type

doubleNum = 30.1

func printInfo(_ value: Any) {
    let varType = type(of: value)
    print("'\(value)' of type '\(varType)'")
}

printInfo(doubleNum)
//'30.1' of type 'Double'
Barsky answered 6/9, 2017 at 5:17 Comment(0)
D
4

I've tried some of the other answers here but milage seems to very on what the underling object is.

However I did found a way you can get the Object-C class name for an object by doing the following:

now?.superclass as AnyObject! //replace now with the object you are trying to get the class name for

Here is and example of how you would use it:

let now = NSDate()
println("what is this = \(now?.superclass as AnyObject!)")

In this case it will print NSDate in the console.

Drudgery answered 16/9, 2014 at 1:31 Comment(0)
N
4

I found this solution which hopefully might work for someone else. I created a class method to access the value. Please bear in mind this will work for NSObject subclass only. But at least is a clean and tidy solution.

class var className: String!{
    let classString : String = NSStringFromClass(self.classForCoder())
    return classString.componentsSeparatedByString(".").last;
}
Nevadanevai answered 7/2, 2015 at 3:20 Comment(0)
A
4

In the latest XCode 6.3 with Swift 1.2, this is the only way I found:

if view.classForCoder.description() == "UISegment" {
    ...
}
Annabelle answered 9/4, 2015 at 2:7 Comment(1)
NOTE: description() returns the class name in the format <swift module name>.<actual class name>, so you want to split the string with a . and get the last token.Butanone
C
4

Many of the answers here do not work with the latest Swift (Xcode 7.1.1 at time of writing).

The current way of getting the information is to create a Mirror and interrogate that. For the classname it is as simple as:

let mirror = Mirror(reflecting: instanceToInspect)
let classname:String = mirror.description

Additional information about the object can also be retrieved from the Mirror. See http://swiftdoc.org/v2.1/type/Mirror/ for details.

Czardom answered 11/11, 2015 at 17:12 Comment(2)
What's wrong with the answers https://mcmap.net/q/83051/-how-do-i-print-the-type-or-class-of-a-variable-in-swift and https://mcmap.net/q/83051/-how-do-i-print-the-type-or-class-of-a-variable-in-swift? Both seem to work quite well with Swift 2. (Haven't checked the other ones.)Eun
I like this as a general solution, but getting "Mirror for ViewController" (extraneous "Mirror for ") - wait, it looks like using ".subjectType " does the trick!Arnett
R
4

Swift version 4:

print("\(type(of: self)) ,\(#function)")
// within a function of a class

Thanks @Joshua Dance

Roundy answered 27/4, 2018 at 3:15 Comment(0)
S
4

Swift 4:

// "TypeName"
func stringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(describing: some) : String(describing: type(of: some))
    return string
}

// "ModuleName.TypeName"
func fullStringType(of some: Any) -> String {
    let string = (some is Any.Type) ? String(reflecting: some) : String(reflecting: type(of: some))
    return string
}

Usage:

print(stringType(of: SomeClass()))     // "SomeClass"
print(stringType(of: SomeClass.self))  // "SomeClass"
print(stringType(of: String()))        // "String"
print(fullStringType(of: String()))    // "Swift.String"
Syndactyl answered 22/12, 2018 at 8:59 Comment(0)
F
3

In lldb as of beta 5, you can see the class of an object with the command:

fr v -d r shipDate

which outputs something like:

(DBSalesOrderShipDate_DBSalesOrderShipDate_ *) shipDate = 0x7f859940

The command expanded out means something like:

Frame Variable (print a frame variable) -d run_target (expand dynamic types)

Something useful to know is that using "Frame Variable" to output variable values guarantees no code is executed.

Farhi answered 15/8, 2014 at 20:41 Comment(0)
B
3

I've found a solution for self-developed classes (or such you have access to).

Place the following computed property within your objects class definition:

var className: String? {
    return __FILE__.lastPathComponent.stringByDeletingPathExtension
}

Now you can simply call the class name on your object like so:

myObject.className

Please note that this will only work if your class definition is made within a file that is named exactly like the class you want the name of.

As this is commonly the case the above answer should do it for most cases. But in some special cases you might need to figure out a different solution.


If you need the class name within the class (file) itself you can simply use this line:

let className = __FILE__.lastPathComponent.stringByDeletingPathExtension

Maybe this method helps some people out there.

Bono answered 18/12, 2014 at 0:20 Comment(0)
I
3

Based on the answers and comments given by Klass and Kevin Ballard above, I would go with:

println(_stdlib_getDemangledTypeName(now).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon?).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(soon!).componentsSeparatedByString(".").last!)

println(_stdlib_getDemangledTypeName(myvar0).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar1).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar2).componentsSeparatedByString(".").last!)
println(_stdlib_getDemangledTypeName(myvar3).componentsSeparatedByString(".").last!)

which will print out:

"NSDate"
"ImplicitlyUnwrappedOptional"
"Optional"
"NSDate"

"NSString"
"PureSwiftClass"
"Int"
"Double"
Importance answered 1/1, 2015 at 12:15 Comment(2)
I think this is the better answer.Disconnection
I ended up using in Swift 1.2 the following: toString(self.dynamicType).componentsSeparatedByString(".").last!, obviously I was in an object context and able to reference self.Salpiglossis
P
3
let i: Int = 20


  func getTypeName(v: Any) -> String {
    let fullName = _stdlib_demangleName(_stdlib_getTypeName(i))
    if let range = fullName.rangeOfString(".") {
        return fullName.substringFromIndex(range.endIndex)
    }
    return fullName
}

println("Var type is \(getTypeName(i)) = \(i)")
Pedigo answered 22/1, 2015 at 23:18 Comment(0)
S
2

There appears to be no generic way to print the type name of an arbitrary value's type. As others have noted, for class instances you can print value.className but for primitive values it appears that at runtime, the type information is gone.

For instance, it looks as if there's not a way to type: 1.something() and get out Int for any value of something. (You can, as another answer suggested, use i.bridgeToObjectiveC().className to give you a hint, but __NSCFNumber is not actually the type of i -- just what it will be converted to when it crosses the boundary of an Objective-C function call.)

I would be happy to be proven wrong, but it looks like the type checking is all done at compile time, and like C++ (with RTTI disabled) much of the type information is gone at runtime.

Subacid answered 3/6, 2014 at 16:41 Comment(5)
Can you give an example of using className to print "NSDate" for the variable "now" in my example that works in Xcode6's playground? As far as I can tell, className is not defined on Swift objects, even those that are subclasses of NSObject.Squish
It appears 'className' is available for objects that descend from NSObject, but only when developing for mac, not for iOS. There appears to be no workaround at all for iOS.Squish
Yeah, the real takeaway here appears to be that, in the general case, type information is gone at runtime in swift.Subacid
I'm curious how the REPL is able to print the types of values, though.Squish
The REPL is almost certainly interpreted and not compiled, which would easily explain itSubacid
T
2

This is how you get a type string of your object or Type which is consistent and takes into account to which module the object definition belongs to or nested in. Works in Swift 4.x.

@inline(__always) func typeString(for _type: Any.Type) -> String {
    return String(reflecting: type(of: _type))
}

@inline(__always) func typeString(for object: Any) -> String {
    return String(reflecting: type(of: type(of: object)))
}

struct Lol {
    struct Kek {}
}

// if you run this in playground the results will be something like
typeString(for: Lol.self)    //    __lldb_expr_74.Lol.Type
typeString(for: Lol())       //    __lldb_expr_74.Lol.Type
typeString(for: Lol.Kek.self)//    __lldb_expr_74.Lol.Kek.Type
typeString(for: Lol.Kek())   //    __lldb_expr_74.Lol.Kek.Type
Teak answered 19/7, 2018 at 12:59 Comment(0)
L
1

Not exactly what you are after, but you can also check the type of the variable against Swift types like so:

let object: AnyObject = 1

if object is Int {
}
else if object is String {
}

For example.

Leffler answered 22/4, 2015 at 11:59 Comment(0)
R
1

Xcode 7.3.1, Swift 2.2:

String(instanceToPrint.self).componentsSeparatedByString(".").last

Ritual answered 24/6, 2016 at 22:24 Comment(0)
H
1

Swift 3.0, Xcode 8

With the following code you can ask an instance for its class. You can also compare two instances, wether having the same class.

// CREATE pure SWIFT class
class MySwiftClass {
    var someString : String = "default"
    var someInt    : Int = 5
}

// CREATE instances
let firstInstance = MySwiftClass()
let secondInstance = MySwiftClass()
secondInstance.someString = "Donald"
secondInstance.someInt = 24

// INSPECT instances
if type(of: firstInstance) === MySwiftClass.self {
    print("SUCCESS with ===")
} else {
    print("PROBLEM with ===")
}

if type(of: firstInstance) == MySwiftClass.self {
    print("SUCCESS with ==")
} else {
    print("PROBLEM with ==")
}

// COMPARE CLASS OF TWO INSTANCES
if type(of: firstInstance) === type(of: secondInstance) {
    print("instances have equal class")
} else {
    print("instances have NOT equal class")
}
Herriot answered 10/11, 2016 at 11:9 Comment(0)
D
0

This is also handy when checking if an object is a type of a class:

if someObject is SomeClass {
    //someObject is a type of SomeClass
}
Dyane answered 19/1, 2017 at 10:25 Comment(0)
B
0

Please have a look at the below code snippet and let me know if you are looking for something like below or not.

var now = NSDate()
var soon = now.addingTimeInterval(5.0)

var nowDataType = Mirror(reflecting: now)
print("Now is of type: \(nowDataType.subjectType)")

var soonDataType = Mirror(reflecting: soon)
print("Soon is of type: \(soonDataType.subjectType)")
Bookstand answered 12/7, 2017 at 3:57 Comment(0)
E
0

Another important aspect that influences the class name returned from String(describing: type(of: self)) is Access Control.

Consider the following example, based on Swift 3.1.1, Xcode 8.3.3 (July 2017)

func printClassNames() {

    let className1 = SystemCall<String>().getClassName()
    print(className1) // prints: "SystemCall<String>"

    let className2 = DemoSystemCall().getClassName()
    print(className2) // prints: "DemoSystemCall"

    // private class example
    let className3 = PrivateDemoSystemCall().getClassName()
    print(className3) // prints: "(PrivateDemoSystemCall in _0FC31E1D2F85930208C245DE32035247)" 

    // fileprivate class example
    let className4 = FileprivateDemoSystemCall().getClassName()
    print(className4) // prints: "(FileprivateDemoSystemCall in _0FC31E1D2F85930208C245DE32035247)" 
}

class SystemCall<T> {
    func getClassName() -> String {
        return String(describing: type(of: self))
    }
}

class DemoSystemCall: SystemCall<String> { }

private class PrivateDemoSystemCall: SystemCall<String> { }

fileprivate class FileprivateDemoSystemCall: SystemCall<String> { }

As you can see, all classes in this example have different levels of access control which influence their String representation. In case the classes have private or fileprivate access control levels, Swift seems to append some kind of identifier related to the "nesting" class of the class in question.

The result for both PrivateDemoSystemCall and FileprivateDemoSystemCall is that the same identifier is appended because they both are nested in the same parent class.

I have not yet found a way to get rid of that, other than some hacky replace or regex function.

Just my 2 cents.

Enlighten answered 27/7, 2017 at 8:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.