How to set a member variable value using reflection in Swift? - ios

I've read through numerous tutorials and tried countless things to get this to work but can't seem to find a solution.
All I want to do is use reflection to set the value for a named member variable. I can read the values just fine, but how do I write a value?
Here is my sample code:
class MyObject
{
public var myString : String = "Not working"
}
func test()
{
let value = "It works!"
let member = "myString"
var myObject = MyObject()
let mirror = Mirror(reflecting: myObject)
for (_, var attr) in mirror.children.enumerated() {
if attr.label == member {
print("Setting value of \(member)")
// attempt to set the member variable value
attr.value = value
break
}
}
print("New value: \(myObject.myString)")
}
Running this example, the output prints the old value of myString. I'm using Swift 4 for iOS.
Any help would be appreciated. Thank you!

Unfortunately, you cannot modify value with built-in Mirror.
Maybe try Runtime named library instead (which's the successor of now deprecated Reflection library).
OR
You can make it without reflection if it is acceptable for you, like:
class MyObject: NSObject {
#objc public var myString : String = "Not working"
}
func test() {
let value = "It works!"
let member = "myString"
let myObject = MyObject()
myObject.setValue(value, forKey: member)
print("New value: \(myObject.myString)")
}
Hope it helps you.

Swift's reflection capabilities are based around a struct called
Mirror. You create a mirror for a particular subject and the
mirror will then let you query it.
Means with Mirror you can not modify the subject in your case MyObject.
Read HERE for more info.
EDIT:
You can simply update your class property as shown below:
func test() {
let myObject = MyObject()
myObject.myString = "It works!"
print("New value: \(myObject.myString)") // "New value: It works!"
}

Related

What's the difference between : and = in swift

Sorry if the title is rather confusing, but I'm curious to know the difference between these two lines:
var title = String()
var title: String
Is one being initialized and one only be declared? Which is more correct?
For example, if I have a struct should I use one of the other?
So the reason I ask this is because I'm learning about how to grab some JSON from a url and then display it in my app. One of the new ways of doing so is using Decodable. So, I have a struct in a model class like so:
struct Videos: Decodable {
var title = String()
var number_of_views : Int
var thumbnail_image_name: String
var channel: Channel
var duration: Int
}
In another class I have this:
URLSession.shared.dataTask(with: url){(data,response,error) in
if(error != nil){
print(error!)
return
}
guard let data = data else { return }
do{
self.Videos2 = try JSONDecoder().decode([Videos].self, from: data)
//self.collectionView?.reloadData()
}catch let jsonErr{
print(jsonErr)
}
}.resume()
So, should I declare or initialize the variables in my struct? I'm assuming I should just declare them like so:
var title: String?
Would that be the correct syntax in my struct?
UPDATE:
I understand this question was more broad then I originally proposed it to be. I'm sorry about that, but thank you so much for all your great answers that clarified a lot up for me.
The difference is that : defines the type of your variable, whereas = assigns an actual value to the variable.
So:
var title = String()
This calls the initializer of the String type, creating a new String instance. It then assigns this value to title. The type of title is inferred to be String because you're assigning an object of type String to it; however, you could also write this line explicitly as:
var title: String = String()
This would mean you are declaring a title variable of type String, and assigning a new String to it.
var title: String
This simply says you're defining a variable of type String. However, you are not assigning a value to it. You will need to assign something to this variable before you use it, or you will get a compile error (and if this is a property rather than just a variable, you'll need to assign it before you get to the end of your type's init() method, unless it's optional with ? after it, in which case it gets implicitly initialized to nil).
EDIT: For your example, I'd probably declare all the variables using let and :, assuming that your JSON provides values for all of those properties. The initializer generated by Decodable should then set all the properties when you create the object. So, something like:
struct Videos: Decodable {
let title: String
let number_of_views : Int
let thumbnail_image_name: String
let channel: Int
let duration: Int
}
This initializes a value
var title = String()
This declares a value but does not initialize it
var title: String
If you attempt to use the latter, such as print(title), you will get a compiler error stating Variable 'title' used before being initialized
It does not matter whether the value is a class or a struct.
The = operator is the assignment operator, it assigns a value to the object on the left of the =
Typically, class or struct properties are declared but not initialized until the init() is called. A simple class might be
class MyClass {
let myProperty: String
init(aString: String) {
self.myProperty = aString
}
}
Whereas inside the scope of a function you may declare a local variable that only lives inside the scope of the function.
func doSomethingToAString(aString: String) -> String {
let extraString = "Something"
let amendedString = aString + extraString
return amendedString
}
In your specific example, the struct synthesizes an initializer that will allow you to initialize the struct with all the values needed to fill your properties. The initializer generated by Decodable should then set all the properties when you create a Videos struct, you will do it something like:
let aVideos = Videos(title: "My Title", number_of_views: 0, thumbnail_image_name: "ImageName", channel: Channel(), duration: 10)
Is one being initialized and one only be declared?
Yes, meaning that the declared cannot be used. If you tried to set a value for it, you would get a compile-time error:
variable 'title' passed by reference before being initialized
Which is more correct?
There is no rule of thumb to determine which is more correct, that would be depends on is there a need to initialize title directly.
On another hand, when it comes to declare properties for a class, saying var title = String() means that you are give title an initial value ("") which means that you are able to create an instance of this class directly, example:
class Foo {
var title = String()
}
let myFoo = Foo()
However, if title declared as var title: String, you will have to implement the init for Foo:
class Foo {
var title: String
init(title: String) {
self.title = title
}
}
let myFoo = Foo(title: "")
Also, you have an option to declare it as lazy:
lazy var title = String()
which means:
A lazy stored property is a property whose initial value is not
calculated until the first time it is used. You indicate a lazy stored
property by writing the lazy modifier before its declaration.
Properties - Lazy Stored Properties

Get the class type name of a UIView subclass in Swift [duplicate]

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!.
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.
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.
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>"
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
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.
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"
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
You can use reflect to get information about object.
For example name of object class:
var classname = reflect(now).summary
Xcode 8 Swift 3.0 use type(of:)
let className = "\(type(of: instance))"
I had luck with:
let className = NSStringFromClass(obj.dynamicType)
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
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
In Swift 3.0, you can use type(of:), as dynamicType keyword has been removed.
To get a type of object or class of object in Swift, you must need to use a type(of: yourObject)
type(of: yourObject)
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.
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'
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.
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;
}
In the latest XCode 6.3 with Swift 1.2, this is the only way I found:
if view.classForCoder.description() == "UISegment" {
...
}
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.
Swift version 4:
print("\(type(of: self)) ,\(#function)")
// within a function of a class
Thanks #Joshua Dance
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.
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.
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"
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)")
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"
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.
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
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.
Xcode 7.3.1, Swift 2.2:
String(instanceToPrint.self).componentsSeparatedByString(".").last

didSet in Swift has a weird knock-on effect on mutating func

I just learned that mutating func is just a curried func with first parameter as inout, so the code below will work and change firstName to "John"
struct Person {
var firstName = "Matt"
mutating func changeName(fn: String) {
firstName = fn
}
}
var p = Person()
let changer = Person.changeName
changer(&p)("John")
p.firstName
but the odd thing happend when I add property observer to p like below, you can see firstName is still "Matt", why?
An interesting note to take ist that the observer is called before the curried setter is called:
struct Person {
var firstName = "Matt"
mutating func changeName(fn: String) {
firstName = fn
}
}
var p: Person = Person() {
didSet {
print("p was set")
}
}
print("1: \(p.firstName)")
let changer = Person.changeName
print("2: \(p.firstName)")
let setter = changer(&p)
print("3: \(p.firstName)")
setter("John")
print("4: \(p.firstName)")
p.changeName("John")
print("5: \(p.firstName)")
This prints:
1: Matt
2: Matt
p was set
3: Matt
4: Matt
p was set
5: John
So it seems that acquiring the setter method on the inout struct performs the actual mutation. This is explained by how inout parameters work semantically: When the parameter is passed to the function its value is copied to a place where the function can mutate it. When the function returns, the value is copied back to the original place, triggering setter observers once, whether the value did change or not.
When we change the way to get the pre-filled curried setter to:
let setter = p.changeName
... the compiler objects:
error: partial application of 'mutating' method is not allowed
It seems that the compiler understands that closing over an inout value is a bad idea, as it is basically taking a reference on a value type.
The closure would let you change the value of the struct at any time, even when the compiler assumes it to be constant. To prevent this unfortunate situation, the compiler simply forbids closing over the inout.
You found a case which fools the compiler and works around the diagnostic. This seems to be an error and it should be filed.
Short version:
struct Foo {
mutating func foo() {}
}
var f = Foo()
let m = Foo.foo
let s = m(&f)
One of the last two lines should emit an error, similar to let x = f.foo.
in the newest accepted proposal 0042-flatten-method-type, self is no more passed as curried function, so this problem is solved in the Swift 3

How do I type check, without including subclasses? [duplicate]

When trying to understand a program, or in some corner-cases, it's useful to find out what type something is. I know the debugger can show you some type information, and you can usually rely on type inference to get away with not specifying the type in those situations, but still, I'd really like to have something like Python's type()
dynamicType (see this question)
Update: this has been changed in a recent version of Swift, obj.dynamicType now gives you a reference to the type and not the instance of the dynamic type.
This one seems the most promising, but I haven't been able to find out the actual type so far.
class MyClass {
var count = 0
}
let mc = MyClass()
# update: this now evaluates as true
mc.dynamicType === MyClass.self
I also tried using a class reference to instantiate a new object, which does work, but oddly gave me an error saying I must add a required initializer:
works:
class MyClass {
var count = 0
required init() {
}
}
let myClass2 = MyClass.self
let mc2 = MyClass2()
Still only a small step toward actually discovering the type of any given object though
edit: I've removed a substantial number of now irrelevant details - look at the edit history if you're interested :)
Swift 3 version:
type(of: yourObject)
Swift 2.0:
The proper way to do this kind of type introspection would be with the Mirror struct,
let stringObject:String = "testing"
let stringArrayObject:[String] = ["one", "two"]
let viewObject = UIView()
let anyObject:Any = "testing"
let stringMirror = Mirror(reflecting: stringObject)
let stringArrayMirror = Mirror(reflecting: stringArrayObject)
let viewMirror = Mirror(reflecting: viewObject)
let anyMirror = Mirror(reflecting: anyObject)
Then to access the type itself from the Mirror struct you would use the property subjectType like so:
// Prints "String"
print(stringMirror.subjectType)
// Prints "Array<String>"
print(stringArrayMirror.subjectType)
// Prints "UIView"
print(viewMirror.subjectType)
// Prints "String"
print(anyMirror.subjectType)
You can then use something like this:
if anyMirror.subjectType == String.self {
print("anyObject is a string!")
} else {
print("anyObject is not a string!")
}
The dynamicType.printClassName code is from an example in the Swift book. There's no way I know of to directly grab a custom class name, but you can check an instances type using the is keyword as shown below. This example also shows how to implement a custom className function, if you really want the class name as a string.
class Shape {
class func className() -> String {
return "Shape"
}
}
class Square: Shape {
override class func className() -> String {
return "Square"
}
}
class Circle: Shape {
override class func className() -> String {
return "Circle"
}
}
func getShape() -> Shape {
return Square() // hardcoded for example
}
let newShape: Shape = getShape()
newShape is Square // true
newShape is Circle // false
newShape.dynamicType.className() // "Square"
newShape.dynamicType.className() == Square.className() // true
Note: that subclasses of NSObject already implement their own className function. If you're working with Cocoa, you can just use this property.
class MyObj: NSObject {
init() {
super.init()
println("My class is \(self.className)")
}
}
MyObj()
As of Xcode 6.0.1 (at least, not sure when they added it), your original example now works:
class MyClass {
var count = 0
}
let mc = MyClass()
mc.dynamicType === MyClass.self // returns `true`
Update:
To answer the original question, you can actually use the Objective-C runtime with plain Swift objects successfully.
Try the following:
import Foundation
class MyClass { }
class SubClass: MyClass { }
let mc = MyClass()
let m2 = SubClass()
// Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground
String.fromCString(class_getName(m2.dynamicType))
String.fromCString(object_getClassName(m2))
// Returns .Some("__lldb_expr_42.MyClass")
String.fromCString(object_getClassName(mc))
If you simply need to check whether the variable is of type X, or that it conforms to some protocol, then you can use is, or as? as in the following:
var unknownTypeVariable = …
if unknownTypeVariable is <ClassName> {
//the variable is of type <ClassName>
} else {
//variable is not of type <ClassName>
}
This is equivalent of isKindOfClass in Obj-C.
And this is equivalent of conformsToProtocol, or isMemberOfClass
var unknownTypeVariable = …
if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> {
//unknownTypeVarible is of type <ClassName or ProtocolName>
} else {
//unknownTypeVariable is not of type <ClassName or ProtocolName>
}
Swift 3:
if unknownType is MyClass {
//unknownType is of class type MyClass
}
For Swift 3.0
String(describing: <Class-Name>.self)
For Swift 2.0 - 2.3
String(<Class-Name>)
Here is 2 ways I recommend doing it:
if let thisShape = aShape as? Square
Or:
aShape.isKindOfClass(Square)
Here is a detailed example:
class Shape { }
class Square: Shape { }
class Circle: Shape { }
var aShape = Shape()
aShape = Square()
if let thisShape = aShape as? Square {
println("Its a square")
} else {
println("Its not a square")
}
if aShape.isKindOfClass(Square) {
println("Its a square")
} else {
println("Its not a square")
}
Old question, but this works for my need (Swift 5.x):
print(type(of: myObjectName))
Comment: I don't see how #JérémyLapointe answers the question. Using type(of:) only works by checking the compile-time information even if the actual type is a more specific subclass. There is now an easier way to dynamically query the type in Swift 5.1 without resorting to dynamicType like #Dash suggests. For more details on where I got this information, see SE-0068: Expanding Swift Self to class members and value types.
Code
Swift 5.1
// Within an instance method context
Self.self
// Within a static method context
self
This allows the use of Self as shorthand for referring to the containing type (in the case of structs, enums, and final class) or the dynamic type (in the case of non-final classes).
Explanation
The proposal explains well why this approach improves on dynamicType:
Introducing Self addresses the following issues:
dynamicType remains an exception to Swift's lowercased keywords rule. This change eliminates a special case that's out of step with
Swift's new standards. Self is shorter and clearer in its intent. It
mirrors self, which refers to the current instance.
It provides an easier way to access static members. As type names grow large, readability suffers.
MyExtremelyLargeTypeName.staticMember is unwieldy to type and read.
Code using hardwired type names is less portable than code that automatically knows its type.
Renaming a type means updating any TypeName references in code. Using self.dynamicType fights against Swift's goals of concision and
clarity in that it is both noisy and esoteric.
Note that self.dynamicType.classMember and TypeName.classMember
may not be synonyms in class types with non-final members.
If you get an "always true/fails" warning you may need to cast to Any before using is
(foo as Any) is SomeClass
If a parameter is passed as Any to your function, you can test on a special type like so :
func isADate ( aValue : Any?) -> Bool{
if (aValue as? Date) != nil {
print ("a Date")
return true
}
else {
print ("This is not a date ")
return false
}
}
Depends on the use case. But let's assume you want to do something useful with your "variable" types. The Swift switch statement is very powerful and can help you get the results you're looking for...
let dd2 = ["x" : 9, "y" : "home9"]
let dds = dd2.filter {
let eIndex = "x"
let eValue:Any = 9
var r = false
switch eValue {
case let testString as String:
r = $1 == testString
case let testUInt as UInt:
r = $1 == testUInt
case let testInt as Int:
r = $1 == testInt
default:
r = false
}
return r && $0 == eIndex
}
In this case, have a simple dictionary that contains key/value pairs that can be UInt, Int or String. In the .filter() method on the dictionary, I need to make sure I test for the values correctly and only test for a String when it's a string, etc. The switch statement makes this simple and safe!
By assigning 9 to the variable of type Any, it makes the switch for Int execute. Try changing it to:
let eValue:Any = "home9"
..and try it again. This time it executes the as String case.
//: Playground - noun: a place where people can play
import UIKit
class A {
class func a() {
print("yeah")
}
func getInnerValue() {
self.dynamicType.a()
}
}
class B: A {
override class func a() {
print("yeah yeah")
}
}
B.a() // yeah yeah
A.a() // yeah
B().getInnerValue() // yeah yeah
A().getInnerValue() // yeah

How do you find out the type of an object (in Swift)?

When trying to understand a program, or in some corner-cases, it's useful to find out what type something is. I know the debugger can show you some type information, and you can usually rely on type inference to get away with not specifying the type in those situations, but still, I'd really like to have something like Python's type()
dynamicType (see this question)
Update: this has been changed in a recent version of Swift, obj.dynamicType now gives you a reference to the type and not the instance of the dynamic type.
This one seems the most promising, but I haven't been able to find out the actual type so far.
class MyClass {
var count = 0
}
let mc = MyClass()
# update: this now evaluates as true
mc.dynamicType === MyClass.self
I also tried using a class reference to instantiate a new object, which does work, but oddly gave me an error saying I must add a required initializer:
works:
class MyClass {
var count = 0
required init() {
}
}
let myClass2 = MyClass.self
let mc2 = MyClass2()
Still only a small step toward actually discovering the type of any given object though
edit: I've removed a substantial number of now irrelevant details - look at the edit history if you're interested :)
Swift 3 version:
type(of: yourObject)
Swift 2.0:
The proper way to do this kind of type introspection would be with the Mirror struct,
let stringObject:String = "testing"
let stringArrayObject:[String] = ["one", "two"]
let viewObject = UIView()
let anyObject:Any = "testing"
let stringMirror = Mirror(reflecting: stringObject)
let stringArrayMirror = Mirror(reflecting: stringArrayObject)
let viewMirror = Mirror(reflecting: viewObject)
let anyMirror = Mirror(reflecting: anyObject)
Then to access the type itself from the Mirror struct you would use the property subjectType like so:
// Prints "String"
print(stringMirror.subjectType)
// Prints "Array<String>"
print(stringArrayMirror.subjectType)
// Prints "UIView"
print(viewMirror.subjectType)
// Prints "String"
print(anyMirror.subjectType)
You can then use something like this:
if anyMirror.subjectType == String.self {
print("anyObject is a string!")
} else {
print("anyObject is not a string!")
}
The dynamicType.printClassName code is from an example in the Swift book. There's no way I know of to directly grab a custom class name, but you can check an instances type using the is keyword as shown below. This example also shows how to implement a custom className function, if you really want the class name as a string.
class Shape {
class func className() -> String {
return "Shape"
}
}
class Square: Shape {
override class func className() -> String {
return "Square"
}
}
class Circle: Shape {
override class func className() -> String {
return "Circle"
}
}
func getShape() -> Shape {
return Square() // hardcoded for example
}
let newShape: Shape = getShape()
newShape is Square // true
newShape is Circle // false
newShape.dynamicType.className() // "Square"
newShape.dynamicType.className() == Square.className() // true
Note: that subclasses of NSObject already implement their own className function. If you're working with Cocoa, you can just use this property.
class MyObj: NSObject {
init() {
super.init()
println("My class is \(self.className)")
}
}
MyObj()
As of Xcode 6.0.1 (at least, not sure when they added it), your original example now works:
class MyClass {
var count = 0
}
let mc = MyClass()
mc.dynamicType === MyClass.self // returns `true`
Update:
To answer the original question, you can actually use the Objective-C runtime with plain Swift objects successfully.
Try the following:
import Foundation
class MyClass { }
class SubClass: MyClass { }
let mc = MyClass()
let m2 = SubClass()
// Both of these return .Some("__lldb_expr_35.SubClass"), which is the fully mangled class name from the playground
String.fromCString(class_getName(m2.dynamicType))
String.fromCString(object_getClassName(m2))
// Returns .Some("__lldb_expr_42.MyClass")
String.fromCString(object_getClassName(mc))
If you simply need to check whether the variable is of type X, or that it conforms to some protocol, then you can use is, or as? as in the following:
var unknownTypeVariable = …
if unknownTypeVariable is <ClassName> {
//the variable is of type <ClassName>
} else {
//variable is not of type <ClassName>
}
This is equivalent of isKindOfClass in Obj-C.
And this is equivalent of conformsToProtocol, or isMemberOfClass
var unknownTypeVariable = …
if let myClass = unknownTypeVariable as? <ClassName or ProtocolName> {
//unknownTypeVarible is of type <ClassName or ProtocolName>
} else {
//unknownTypeVariable is not of type <ClassName or ProtocolName>
}
Swift 3:
if unknownType is MyClass {
//unknownType is of class type MyClass
}
For Swift 3.0
String(describing: <Class-Name>.self)
For Swift 2.0 - 2.3
String(<Class-Name>)
Here is 2 ways I recommend doing it:
if let thisShape = aShape as? Square
Or:
aShape.isKindOfClass(Square)
Here is a detailed example:
class Shape { }
class Square: Shape { }
class Circle: Shape { }
var aShape = Shape()
aShape = Square()
if let thisShape = aShape as? Square {
println("Its a square")
} else {
println("Its not a square")
}
if aShape.isKindOfClass(Square) {
println("Its a square")
} else {
println("Its not a square")
}
Old question, but this works for my need (Swift 5.x):
print(type(of: myObjectName))
Comment: I don't see how #JérémyLapointe answers the question. Using type(of:) only works by checking the compile-time information even if the actual type is a more specific subclass. There is now an easier way to dynamically query the type in Swift 5.1 without resorting to dynamicType like #Dash suggests. For more details on where I got this information, see SE-0068: Expanding Swift Self to class members and value types.
Code
Swift 5.1
// Within an instance method context
Self.self
// Within a static method context
self
This allows the use of Self as shorthand for referring to the containing type (in the case of structs, enums, and final class) or the dynamic type (in the case of non-final classes).
Explanation
The proposal explains well why this approach improves on dynamicType:
Introducing Self addresses the following issues:
dynamicType remains an exception to Swift's lowercased keywords rule. This change eliminates a special case that's out of step with
Swift's new standards. Self is shorter and clearer in its intent. It
mirrors self, which refers to the current instance.
It provides an easier way to access static members. As type names grow large, readability suffers.
MyExtremelyLargeTypeName.staticMember is unwieldy to type and read.
Code using hardwired type names is less portable than code that automatically knows its type.
Renaming a type means updating any TypeName references in code. Using self.dynamicType fights against Swift's goals of concision and
clarity in that it is both noisy and esoteric.
Note that self.dynamicType.classMember and TypeName.classMember
may not be synonyms in class types with non-final members.
If you get an "always true/fails" warning you may need to cast to Any before using is
(foo as Any) is SomeClass
If a parameter is passed as Any to your function, you can test on a special type like so :
func isADate ( aValue : Any?) -> Bool{
if (aValue as? Date) != nil {
print ("a Date")
return true
}
else {
print ("This is not a date ")
return false
}
}
Depends on the use case. But let's assume you want to do something useful with your "variable" types. The Swift switch statement is very powerful and can help you get the results you're looking for...
let dd2 = ["x" : 9, "y" : "home9"]
let dds = dd2.filter {
let eIndex = "x"
let eValue:Any = 9
var r = false
switch eValue {
case let testString as String:
r = $1 == testString
case let testUInt as UInt:
r = $1 == testUInt
case let testInt as Int:
r = $1 == testInt
default:
r = false
}
return r && $0 == eIndex
}
In this case, have a simple dictionary that contains key/value pairs that can be UInt, Int or String. In the .filter() method on the dictionary, I need to make sure I test for the values correctly and only test for a String when it's a string, etc. The switch statement makes this simple and safe!
By assigning 9 to the variable of type Any, it makes the switch for Int execute. Try changing it to:
let eValue:Any = "home9"
..and try it again. This time it executes the as String case.
//: Playground - noun: a place where people can play
import UIKit
class A {
class func a() {
print("yeah")
}
func getInnerValue() {
self.dynamicType.a()
}
}
class B: A {
override class func a() {
print("yeah yeah")
}
}
B.a() // yeah yeah
A.a() // yeah
B().getInnerValue() // yeah yeah
A().getInnerValue() // yeah

Resources