Reputation: 24247
I am aware of this question regarding how we can get a readable class name of an objective-c class in Swift.
What I want to achieve is getting the readable class name of a Swift class from inside objective-c without mangling the class name with the module.
So if I have a Swift class:
class Foo: NSObject{}
Then inside Objective-C I would love to use the convenient NSStringFromClass to convert the class name to a string.
I would expect NSStringFromClass([Foo class])
to return @"Foo"
but instead it returns @"Bar.Foo"
withBar
being the module name.
I came across this Gist but it seems a little hacky and messy, is there a better way? Something that doesn't include typing the class name manually into a string would be preferred.
Upvotes: 19
Views: 19114
Reputation: 3439
The reason you get "Bar.Foo"
is because swift is a namespace language. I'm assuming the application you were running this in was named Bar. Hence you may get your class name using the following:
let nameSpaceClassName = NSStringFromClass(Foo)
let className = nameSpaceClassName.componentsSeparatedByString(".").last! as String
Edit:
The above is an extremely old answer that should be changed based on more recent introductions in the Swift library (from 3 and 4 at least). Note the following use of the Mirroring interfaces to properly extract a class's metadata:
import Foundation
/// A protocol that provides demangled information regarding core Swift structure naming components in a usable way.
public protocol StructureNameReflectable {
/**
An ordered list of domain named based components for the structure.
- Example: A simple example would be:
```
class Dog: NSObject {
class Retriever: NSOjbect {}
}
let retriever = Retriever()
```
`retriever.structuredName` would output `["Dog", "Retriever"]`
*/
static var structureNameComponents: [String] { get }
///Outputs the structure's name in a string based form minus namespacing
static var structureName: String { get }
///Outputs the structure's name in a string based form with namespacing
static var namespacedStructureName: String { get }
///Outputs the bundle the structure is contained in
static var bundle: Bundle { get }
}
extension StructureNameReflectable {
public static var structureNameComponents: [String] {
let type = Mirror(reflecting: self).subjectType
let structureNameComponents = "\(type)".components(separatedBy: ".")
return structureNameComponents
}
public static var structureName: String {
var structureNameComponents = self.structureNameComponents
if structureNameComponents.count > 1 && structureNameComponents.last == "Type" {
structureNameComponents.removeLast()
}
return structureNameComponents.last!
}
public static var namespacedStructureName: String {
return structureNameComponents.joined(separator: ".")
}
}
extension StructureNameReflectable where Self: NSObject {
public static var bundle: Bundle {
return Bundle(for: self)
}
public static var className: String {
return structureName
}
}
extension NSObject: StructureNameReflectable { }
Hopefully the above will give guidance for the consistently improper use of String(describing:)
.
Upvotes: 11
Reputation: 1177
On the latest Swift below worked for me:
NSStringFromClass(type(of: yourClass!.self))
Upvotes: -1
Reputation: 4105
Swift 5.1 solution for NSStringFromClass
If you want the string description of a class name (say CustomTableViewCell
) use:
String(describing: CustomTableViewCell.self)
Upvotes: 2
Reputation: 10170
Just put @objc(YourClassName)
in your swift class:
@objc(YourClassName)
class YourClassName: NSObject {
}
And you can use NSStringFromClass like this:
NSStringFromClass(YourClassName.self)
It should also work from Objective-C then.
With Swift 2.1 a comment to this answer states that this is sufficient:
class YourClassName: NSObject {
}
And just use:
var str = String(YourClassName)
I have not tested this from Objective-C code myself though.
There's been a edit-suggestions that want to use this instead for Swift 4:
var str = String(describing: YourClassName.self)
I've not tested this from Objective-C though.
Upvotes: 39
Reputation: 4178
In objective-c your best option is:
NSString *yourCellName = NSStringFromClass([yourCell class]).pathExtension;
Upvotes: 6
Reputation: 9296
Try it with Swift 2.0:
self.description().componentsSeparatedByString(".").last!
Upvotes: -3