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.
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.
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:)
.
In objective-c your best option is:
NSString *yourCellName = NSStringFromClass([yourCell class]).pathExtension;
Working solution for this in Swift 2.1 is
String(MyClass)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With