Search code examples
swiftreflectionswift-extensions

In a Swift extension, get the actual calling object?


Say we are in an instance of SomeClass, consider this simple call

NSNotificationCenter.defaultCenter().addObserver(
 self,
 selector: #selector(SomeClass.fixer(_:)),
 name:"FixerNote",
 object:nil)

Say we decide to make an extension to save typing, that will look like this ...

"FixerNote".does( #selector(SomeClass.fixer(_:)) )

Here's the extension...

public extension String
    {
    func does(s:Selector)
        {
        NSNotificationCenter.defaultCenter().addObserver
           .. here, you need the actual SomeClass that called us .. ,
            selector: s,
            name:self,
            object:nil)
        }
}

How to know which object called the extension??

(NB, I realize you could pass it in or use it as the base :) )

Can you do such a thing in Swift? Can you find out who called you?

A similar issue: in the example, could you find out what object a selector ("s" in the example) belongs to ??


Solution

  • It's generally possible to iterate the stack trace of a program, but you need debug symbols to figure out where the self parameter of a method lives, and it might not even be anywhere anymore on an optimized build, or the caller might have been inlined, or have suffered some other destructive fate at the whim of the optimizer. So while it's possible to get an approximation of what method called you, it's not possible to get the self parameter of your caller on a deployed, symbol-less, optimized build.

    And no, it's not possible to get a class out of a selector either. A selector is really just a string that identifies a method name, like "fixer:". The #selector() syntax only ensures that the compiler generates the correct selector name for a method (considering eventual @objc annotations) and helps refactoring tools understand what is happening.