31

Is there an equivalent of NSStringFromClass in Swift that gives a user-readable version of the class name? I've tried to use it with a native Swift class I created, but as you can see, the result seems to be the compiler's internal representation of the class name:

println(NSStringFromClass(MyClass.self)) 

Result:

_TtC5test7MyClass 

I've tried adding the @objc attribute to the class, and making it a subclass of NSObject, but it makes no difference. I've discovered that if I replace MyClass with an Objective-C class of the same name, and import this in the bridging header, it gives me 'MyClass', but this shouldn't be necessary.

Another option would be to make a protocol for this, which each class I want to use in this way must conform to:

protocol Nameable { class var className: String { get } } 

However, it would be easier to have a built-in way to do this in the language.

15 Answers 15

64

You can now just do:

String(MyClass) 
Sign up to request clarification or add additional context in comments.

3 Comments

This makes me unreasonably happy! Thanks Natasha robot.
In Swift 3 this doesn't work anymore. The Swift 3 converter changed it to String(describing: MyClass) but that's not working either.
@shim have you tried String(describing: self) or just passing object let object = MyClass() String(describing: object)
25

new format based on xcode 6 beta 5.

(project_name).(class_name)

func getName(classType:AnyClass) -> String { let classString = NSStringFromClass(classType.self) let range = classString.rangeOfString(".", options: NSStringCompareOptions.CaseInsensitiveSearch, range: Range<String.Index>(start:classString.startIndex, end: classString.endIndex), locale: nil) return classString.substringFromIndex(range!.endIndex) } 

Latest 6.3 Xcode Swift 1.2

if you need an extension or you can put this on any common object:

public extension NSObject{ public class var nameOfClass: String{ return NSStringFromClass(self).componentsSeparatedByString(".").last! } public var nameOfClass: String{ return NSStringFromClass(self.dynamicType).componentsSeparatedByString(".").last! } } 

3 Comments

classType.self should just be written as classType
this also works: NSStringFromClass(self).componentsSeparatedByString(".").last!
As @NatashaTheRobot states below. Just use String(MyClass) now.
19

Swift 3

type(of: self) prints ModuleName.ClassName

String(describing: type(of: self)) prints ClassName

Comments

5

At the moment, there's no reliable way to do this. See an Apple developer's comment on https://devforums.apple.com/thread/227425

Swift does not currently have much in the way of introspection.

There is some introspection machinery that is used for the playgrounds. I don't know if that is intended to be API.

Some Swift methods and variables can be examined using the Objective-C runtime's introspection. That's likely to be the best solution today.

Swift does have the notion of a metatype, somewhat analogous to the Class type in Objective C. You can find it using TypeName.self, e.g.:

class Foo { @required init() { } } var normalFoo : Foo = Foo() var fooType : Foo.Type = Foo.self; var fooFromMetatype : Foo = fooType(); 

Perhaps, by release time, metatypes will include more introspection abilities. I suggest filing a Radar feature request for this.

Comments

5

In Swift 2 beta 4 you can get to the information via the type object:

let className = "\(String.self)" // gives: "Swift.String" 

or if you have an instance:

let s = "Hello World" let className = "\(s.dynamicType)" // gives: "Swift.String" 

You get the Module.Class result, like:

Swift.String ABC.MyGenericClass<Swift.Int> 

Funny enough the Type object returned does not seem to conform to the CustomStringConvertible protocol. Hence it has no 'description' property, though the "" pattern still does the right thing.

P.S.: Before b4 the same could be accomplished via reflect(obj.dynamicType).summary.

1 Comment

That's cool but until they have an explicit className() method somewhere in there I am a little wary. Summary might be the class name right now but there are no guarantees it'll stay that way.
3

In Swift v3.0, this worked for me:

String.init(describing: self.self) 

Comments

3

----- Updated -----

As @ThomasW mentioned, for Swift 4, we need to use String(describing:type(of:self))

----- Old post ----

I prefer to use String(self.dynamicType)

Use it in my project https://github.com/JakeLin/SwiftWeather/blob/e7165b0919dda53fd7fcba9b43fdfe150d73c6f8/SwiftWeather/ForecastView.swift#L135

2 Comments

For Swift 4 this no longer works, but String(describing:type(of:self)) does.
@ThomasW Thanks, have updated the post to reflect the changes.
1

If you want to have only the name of the class in swift you can parse the string returned by NSStringFromClass().

This is done in nameOfClass.swift of the INSwift Github repository: https://github.com/indieSoftware/INSwift

1 Comment

Note that this only works with class types -- if you try it with say a protocol Swift will complain error: type 'MyProtocol' does not conform to protocol 'AnyObject'
1

You shouls now be able to use the following to retrieve the class name in swift

let nameSpaceClassName = NSStringFromClass(RWTCountryPopoverViewController.self) let className = nameSpaceClassName.componentsSeparatedByString(".").last! as String 

Comments

1

This is a bit shorter. No need of NSStringFromClass

MyObject.self.description().componentsSeparatedByString(".").last! 

Comments

1

Here is Swift 3+, Xcode 8+ example with code:

class MySuperbClass{ let a = 4 func getClassName() -> String? { return String(describing: type(of:self)).components(separatedBy: ".").first } } let className = String(describing: type(of:MySuperbClass.self)).components(separatedBy: ".").first //className = "MySuperbClass" let classNameFromObject = MySuperbClass().getClassName() //classNameFromObject = "MySuperbClass" 

Comments

1

Swift 4

super.init(nibName:String(describing:MyClass.self), bundle: nil) 

Comments

0
myObject.description().componentsSeparatedByString(" ").first! 

This is not exactly what you want - it will add an unwanted leading '<' and trailing ':'. But when I am debugging I value speed over neatness so this quick + dirty trick worked for me.

Comments

0

Swift 3

NSStringFromClass(self).components(separatedBy: ".").last! 

Comments

0

In latest version of swift, below works for me:

NSStringFromClass(type(of: device!.self)) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.