Swift msethod-swizzle

Swift 当中也可以使用 method swizzle 在运行时进行方法交换,通常在某种情况下很有用,比如统计页面 Button 点击了多少次,可以扩展 UIButton 来实现,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
extension UIButton{
class func swipButtonAction(){
struct T {
static var swizzle: Bool = {
let cls: AnyClass = UIButton.self

let originalSelector = #selector(UIButton.sendAction(_:to:for:))
let swizzleSelector = #selector(UIButton.swizzle_sendAction(action:to:forEvent:))

let origin_method = class_getInstanceMethod(cls, originalSelector)
let swizzle_method = class_getInstanceMethod(cls, swizzleSelector)

// 交换两个方法实现
method_exchangeImplementations(origin_method, swizzle_method)

return false
}()
}

_ = T.swizzle
}

// 定义要交换的函数
public func swizzle_sendAction(action: Selector,
to: AnyClass!,
forEvent: UIEvent!){
// 累加器
struct button_tap_count{
static var count = 0
}

button_tap_count.count += 1
print(button_tap_count.count)
// 看似好像调用了自己构成死循环,但是 我们其实已经将两个方法名的实现进行了调换 所以 其实我们调用的是 方法sendAction:to:forEvent 的实现 这样就可以在不破环原先方法结构的基础上进行交换实现
swizzle_sendAction(action: action, to: to, forEvent: forEvent)
}
}

参考

swift swizzle