Swift与OC混编Swizzling时class_getInstanceMethod返回nil问题
问题根源
你踩了两个关键的坑:
- 原方法是类方法,你却用了实例方法的查找函数
原Objective-C方法是+开头的类方法,这类方法存在于类的元类方法列表里,而你调用的class_getInstanceMethod只负责查找类的实例方法(-开头的方法),所以必然返回nil。 - 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
相关产品推荐
相关产品推荐

