Swift + Objective C 混合 class_getInstanceMethod 返回 nil

问题描述 投票:0回答:1

我正在使用 AsyndDisplayKit/Texture,其中:

https://github.com/TextureGroup/Texture/blob/923901a1cebf0b6c51627aca2a6748dee84af143/Source/ASTextNode.mm#L934

ASTextNode有这个功能:

+ (CGColorRef)_highlightColorForStyle:(ASTextNodeHighlightStyle)style
{
  return [UIColor colorWithWhite:(style == ASTextNodeHighlightStyleLight ? 0.0 : 1.0) alpha:1.0].CGColor;
}

不幸的是,它没有暴露。所以我无法更改突出显示颜色。所以我尝试用这个来混合它:

extension ASTextNode {
    
    @objc func swizzledHighlightColor() -> CGColor {
        return UIColor.red.cgColor
    }
    
    static func swizzle() {
        let originalSelector = NSSelectorFromString("_highlightColorForStyle:")
        
        let swizzledSelector = #selector(ASTextNode.swizzledHighlightColor)
        
        print("originalSelector: \(originalSelector)")
        print("swizzledSelector: \(swizzledSelector)")
        
        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
        
        print("originalMethod: \(String(describing: originalMethod))")
        print("swizzledMethod: \(String(describing: swizzledMethod))")
        
        if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
}

这里,

method_exchangeImplementations
失败,因为
originalMethod
得到的
class_getInstanceMethod
返回零。上面的输出是:

originalSelector: _highlightColorForStyle:
swizzledSelector: swizzledHighlightColor
originalMethod: nil
swizzledMethod: Optional(0x00000001046b5e09)

为了调试,我打印了这个并且它确实有效:

let selectorPerformed = ASTextNode.perform(originalSelector)        
print("selectorPerformed: \(String(describing: selectorPerformed))")

打印:

selectorPerformed: Optional(Swift.Unmanaged<Swift.AnyObject>(_value: <CGColor 0x30333c8c0> [<CGColorSpace 0x303430120> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile; extended range)] ( 1 1 )))

所以,

originalSelector
是正确的。为什么
class_getInstanceMethod
失败了?

编辑:我找到了问题所在。我在下面发布了解决方案。

ios swift objective-c method-swizzling swizzle
1个回答
0
投票

Nvm,我找到了解决方案。我错误地使用了

class_getInstanceMethod

我需要使用

class_getClassMethod
来代替,因为它不是实例方法。

这是可行的解决方案:

extension ASTextNode {

    @objc static func swizzledHighlightColor() -> CGColor {
        return UIColor.red.cgColor
    }
    
    static func swizzle() {
        let originalSelector = NSSelectorFromString("_highlightColorForStyle:")
        let swizzledSelector = #selector(ASTextNode.swizzledHighlightColor)
        
        print("originalSelector: \(originalSelector)")
        print("swizzledSelector: \(swizzledSelector)")
        
        let originalMethod = class_getClassMethod(self, originalSelector)
        let swizzledMethod = class_getClassMethod(self, swizzledSelector)
        
        print("originalMethod: \(String(describing: originalMethod))")
        print("swizzledMethod: \(String(describing: swizzledMethod))")
        
        if let originalMethod = originalMethod, let swizzledMethod = swizzledMethod {
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
        
        let selectorPerformed = ASTextNode.perform(originalSelector)
        print("selectorPerformed: \(String(describing: selectorPerformed))")
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.