Is it possible to obtain a Swift type from a string?
No, it's not possible yet (as a language feature, at least).
What you need is your own type registry. Even with a type registry, you wouldn't be able to get static
constants unless you had a protocol for that:
var typeRegistry: [String: Any.Type] = [:]
func indexType(type: Any.Type)
{
typeRegistry[String(type)] = type
}
protocol Foo
{
static var bar: String { get set }
}
struct X: Foo
{
static var bar: String = "x-bar"
}
struct Y: Foo
{
static var bar: String = "y-bar"
}
indexType(X)
indexType(Y)
typeRegistry // ["X": X.Type, "Y": Y.Type]
(typeRegistry["X"] as! Foo.Type).bar // "x-bar"
(typeRegistry["Y"] as! Foo.Type).bar // "y-bar"
A type registry is something that registers your types using a custom Hashable
type (say a String
or an Int
). You can then use this type registry to reference registered types using custom identifiers (a String
, in this case).
Since Any.Type
by itself isn't all that useful, I constructed an interface Foo
through which I could access a static constant bar
. Because I know that X.Type
and Y.Type
both conform to Foo.Type
, I forced a cast and read the bar
property.
How to create an instance of a class from a String in Swift
You can try this:
func classFromString(_ className: String) -> AnyClass! {
/// get namespace
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String
/// get 'anyClass' with classname and namespace
let cls: AnyClass = NSClassFromString("\(namespace).\(className)")!
// return AnyClass!
return cls
}
use the func like this:
class customClass: UITableView {}
let myclass = classFromString("customClass") as! UITableView.Type
let instance = myclass.init()
How do you find out the type of an object (in Swift)?
Swift 3 version:
type(of: yourObject)
How to get a Swift type name as a string with its namespace (or framework name)
Use String(reflecting:)
:
struct Bar { }
let barName = String(reflecting: Bar.self)
print(barName) // <Module>.Bar
From the Xcode 7 Release Notes:
Type names and enum cases now print and convert to String without
qualification by default.debugPrint
orString(reflecting:)
can still
be used to get fully qualified names.
Get the name (string) of a generic type in Swift
A pure swift way to achieve that is not possible.
A possible workaround is:
class MyClass<T: AnyObject> {
func genericName() -> String {
let fullName: String = NSStringFromClass(T.self)
let range = fullName.rangeOfString(".", options: .BackwardsSearch)
if let range = range {
return fullName.substringFromIndex(range.endIndex)
} else {
return fullName
}
}
}
The limitations relies on the fact that it works with classes only.
If this is the generic type:
class TestClass {}
NSStringFromClass()
returns the full name (including namespace):
// Prints something like "__lldb_expr_186.TestClass" in playground
NSStringFromClass(TestClass.self)
That's why the func searches for the last occurrence of the .
character.
Tested as follows:
var x = MyClass<TestClass>()
x.genericName() // Prints "TestClass"
UPDATE Swift 3.0
func genericName() -> String {
let fullName: String = NSStringFromClass(T.self)
let range = fullName.range(of: ".")
if let range = range {
return fullName.substring(from: range.upperBound)
}
return fullName
}
How to convert a string with the name of a class to the class type itself?
You can get your class back from string
, but you need to use your project's module name while getting class name. If you don't use your module name then it will return nil
because the class name you have referenced earlier is not fully qualified by the module name. You should change the class name string to represent the fully qualified name of your class:
let myClassString = String(MyModule.MyViewController.self)
print(myClassString)
let myClass = NSClassFromString("MyModule.\(myClassString)") as! MyViewController.Type
print(myClass)
How do I print the type or class of a variable in Swift?
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.
Related Topics
Textfield in Swiftui Loses Focus When I Enter a Character
How to Use Nsvisualeffectview to Blend Window with Background
Zposition of Sknode Relative to Its Parent
How to Skip Iterations of a For-In Loop (Swift 3)
Swift - Exit Outer Function from Closure
Modifying an Array Passed as an Argument to a Function in Swift
Swift - Associated Types in Protocol with Where Clause
Showing Notification Banner on MAC with Swift
How to Cast [Int8] to [Uint8] in Swift
Non-Modular Headers of Openssl Library When Using Modulemap for Swift Framework
Fetching Child Sum from Core Data
Xcode 8 Swift 3 Pitch-Altering Sounds
Iwatch: Wkinterfacelabel How to Stop Text from Being Cut Off with "..." at The End of a Label
Firebase and Reading Nested Data Using Swift
Function Builder Not Working When Only One Value