I am looking at the Swift code of the ThemeKit theming library.
In particular I would like to understand the following code in NSColor+ThemeKit.swift:
// ThemeKit.set() replacement to use theme-aware color
@objc public func themeKitSet() {
// call original .set() function
themeKitSet()
// check if the user provides an alternative color
if ThemeManager.shared.isEnabled && isThemeOverriden {
// call ThemeColor.set() function
ThemeColor.color(with: Selector(colorNameComponent)).set()
}
}
There is what appears to be an endless recursive call, but presumably can't be, since the code works fine. This is confirmed by setting a breakpoint on the call to themeKitSet()
. It is not possible to step into the call and execution continues without recursion.
Earlier in the file there is the following call:
swizzleInstanceMethod(cls: NSClassFromString("NSDynamicSystemColor"), selector: #selector(set), withSelector: #selector(themeKitSet))
With the implementation in NSObject+ThemeKit.swift as follows:
/// Swizzle instance methods.
@objc internal class func swizzleInstanceMethod(cls: AnyClass?, selector originalSelector: Selector, withSelector swizzledSelector: Selector) {
guard cls != nil else {
print("Unable to swizzle \(originalSelector): dynamic system color override will not be available.")
return
}
// methods
let originalMethod = class_getInstanceMethod(cls, originalSelector)
let swizzledMethod = class_getInstanceMethod(cls, swizzledSelector)
// add new method
let didAddMethod = class_addMethod(cls, originalSelector, method_getImplementation(swizzledMethod!), method_getTypeEncoding(swizzledMethod!))
// switch implementations
if didAddMethod {
class_replaceMethod(cls, swizzledSelector, method_getImplementation(originalMethod!), method_getTypeEncoding(originalMethod!))
} else {
method_exchangeImplementations(originalMethod!, swizzledMethod!)
}
}
I suspect this is responsible for the magic, but my limited understanding of both Swift and Objective-C is letting me down.
What is happening here? Why is the apparently recursive call not actually recursive?