递归查找 Swift 扩展函数,实际上不是。为什么不?

分数

我正在查看ThemeKit主题库的 Swift 代码

特别是我想了解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()
    }
}

似乎有一个无休止的递归调用,但大概不可能,因为代码工作正常。这通过在调用上设置断点来确认themeKitSet()无法单步执行调用并且不递归地继续执行。

在文件的前面有以下调用:

swizzleInstanceMethod(cls: NSClassFromString("NSDynamicSystemColor"), selector: #selector(set), withSelector: #selector(themeKitSet))

NSObject+ThemeKit.swift 中的实现如下:

/// 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!)
    }
}

我怀疑这是魔法的原因,但我对 Swift 和 Objective-C 的有限理解让我失望。

这里发生了什么?为什么表面上的递归调用实际上不是递归的?

andyvn22

您正确地识别了魔法位:它被称为方法调配,它是一种批量替换现有方法实现的方式。

当方法 swizzling 时,您会themeKitSet经常看到这种看似递归的模式:该调用实际上运行了原始实现,如注释所述。这是因为 swizzling交换了两种方法的实现,在本例中为themeKitSetNSDynamicSystemColor.set

因此,post-swizzleNSDynamicSystemColor.set运行您在那里看到的代码,并themeKitSet成为原始实现。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章