You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift与OC混编Swizzling时class_getInstanceMethod返回nil问题

问题根源

你踩了两个关键的坑:

  1. 原方法是类方法,你却用了实例方法的查找函数
    原Objective-C方法是+开头的类方法,这类方法存在于类的元类方法列表里,而你调用的class_getInstanceMethod只负责查找类的实例方法(-开头的方法),所以必然返回nil。
  2. perform能执行是因为OC的消息转发机制
    当你用ASTextNode.perform(originalSelector)时,OC的消息发送流程会自动去元类里查找类方法,哪怕是私有方法,只要selector存在就能找到实现,这和直接用class_getInstanceMethod查实例方法的逻辑完全不同。
修正后的Swizzle代码

要交换类方法,得用class_getClassMethod,同时还要保证swizzled方法的参数和原方法一致(原方法带style参数,你之前的swizzled方法没有,会导致参数不匹配):

extension ASTextNode {
    // 类方法的swizzle要加@objc class
    @objc class func swizzledHighlightColor(forStyle style: ASTextNodeHighlightStyle) -> CGColor {
        // 交换后调用这个方法其实会走到原实现,这里可以自定义颜色
        return UIColor.red.cgColor
    }
    
    static func swizzle() {
        let originalSelector = NSSelectorFromString("_highlightColorForStyle:")
        let swizzledSelector = #selector(swizzledHighlightColor(forStyle:))
        
        // 用class_getClassMethod获取类方法
        guard let originalMethod = class_getClassMethod(self, originalSelector),
              let swizzledMethod = class_getClassMethod(self, swizzledSelector) else {
            print("Swizzle失败:无法获取目标方法")
            return
        }
        
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
}
额外注意事项
  • 调用swizzle()的时机要早,比如在AppDelegate的didFinishLaunchingWithOptions里,确保在_highlightColorForStyle:被调用前完成交换。
  • 私有方法可能会在框架版本更新时被修改,Swizzle私有方法有兼容性风险,要做好测试。

内容的提问来源于stack exchange,提问作者sudoExclamationExclamation

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 17:43:10