1

I implemented an extension to NSObject to get the dynamic type of my objects:

extension NSObject  {
    var dynamic_type : String {
        get {
            return String(describing: type(of: self))
        }
    }
}

This works perfectly for public classes.

In a class called InitialState dynamic_type would be "InitialState" (this is what I want) But as soon as I change the class to private or fileprivate it is something like "(InitialState in _AF5C6D4A3B423A6F0735A7740F802E5A)" (the parenthesis are also returned)

Why is this and what does the part after "in" mean? How can I get the plain class name for every type of class? (public, private, fileprivate)

I know that I could simply parse the string to get the plain class name but I want to understand what exactly happens and if I maybe am doing it wrong.

  • There's already a [`className`](https://developer.apple.com/documentation/objectivec/nsobject/1411337-classname) property on `NSObject` – Alexander Jan 17 '18 at 17:11
  • 1
    [Private symbols are mangled with a discriminator](https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20171002/040093.html), so that's most likely what you're seeing in your output. But at the end of the day, the string you get back from `String(describing: type(of: self))` is an implementation detail, you shouldn't rely on it. What exactly do you need this for? – Hamish Jan 17 '18 at 17:16
  • @Alexander This method does not exist on iPhones and I develop an iOS app :( –  Jan 17 '18 at 18:44
  • @Hamish I only need this for printing logs. I have a state machine and every state inherits from a superclass (BaseState). In that class I have some logging methods, but I want to see the exact state in the logs and not only the superclass. It's only for debugging, I do not rely on the response in my code. But it looks strange with this long string –  Jan 17 '18 at 18:46
  • @Hamish example: func handleMessage(_ msg: String) { log.error("handleMessage() not implemented for state \(self.dynamic_type)") } (this is a method in the super class) –  Jan 17 '18 at 18:48
  • 1
    @NomisHe You could use `NSStringFromClass(type(of: self))` instead then; that'll give you the name by which the Obj-C runtime sees the class (which can be changed with `@objc(...)`). – Hamish Jan 18 '18 at 14:05
  • @Hamish: That gives me even more strange results, e.g. "_TtC18My_Module_NameP33_AF5C6D4A3B423A6F0735A7740F802E5A12InitialState" instead of just "InitialState" – Simon Hessner Jan 21 '18 at 18:07
  • Oh sorry, completely forgot about @objc(...). If I write @objc(InitialState) before the class name it works. Does this have any side-effects? – Simon Hessner Jan 21 '18 at 18:13
  • 1
    @SimonH Other than requiring that the class inherits from `NSObject`, not really. The class is actually exposed to the Obj-C runtime regardless of the `@objc` attribute. – Hamish Jan 22 '18 at 06:57
  • Ok, so this is a nice workaraound, altough it'd be better if there was a way to get the dynamic type without any additional information without manually needing to annotate... Maybe in Swift 5 :P – Simon Hessner Jan 22 '18 at 13:29

0 Answers0