Method Swizzle

在Swift中也可以用Objective-C运行时来进行Swizzle, 如果想在一个app中监听所有的点击事件,可以这样来做:

extension UIButton {
    class func SSSwizzleSendAction() {
        struct SSSwizzleToken {
            static var onceToken : dispatch_once_t = 0
        }
        dispatch_once(&SSSwizzleToken.onceToken) {
            let cls: AnyClass! = UIButton.self
            
            let originalSelector = Selector("sendAction:to:forEvent:")
            let swizzledSelector = Selector("SSSendAction:to:forEvent:")
            
            let originalMethod =
            class_getInstanceMethod(cls, originalSelector)
            let swizzledMethod =
            class_getInstanceMethod(cls, swizzledSelector)
            
            method_exchangeImplementations(originalMethod, swizzledMethod)
        }
    }
    
    public func SSSendAction(action: Selector,
        to: AnyObject!,
        forEvent: UIEvent!)
    {
        struct SSButtonTapCounter {
            static var count: Int = 0
        }
        
        SSButtonTapCounter.count += 1
        print(SSButtonTapCounter.count)
        SSSendAction(action, to: to, forEvent: forEvent)
    }
}

sendAction:to:forEvent:为被替换的方法,SSSendAction:to:forEvent:为替换后的方法,在运行时,对这两个方法进行了交换,在SSSendAction:to:forEvent:中调用了自己,但是因为交换了两个方法的实现,在调用时就会调用原来的方法。

需要app启动时调用这个SSSendAction:to:forEvent:方法,可以写在UIButton初始化时调用:

extension UIButton {
    override public class func initialize() {
        if self != UIButton.self {
            return
        }
        UIButton.SSSwizzleSendAction()
    }
}

如果Swizzle的是Swift类型的方法,需要将原方法和替换方法加dynamic标记,指明需要动态派发机制。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容