在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标记,指明需要动态派发机制。