首先,實現(xiàn)一個swizzle方法替換People對象run()的IMP為runNew()的IMP,然后用兩種方式調用run()践付,結果會是一樣的嗎粘室?
代碼如下:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let peo = People()
peo.run()
peo.perform(#selector(People.run))
self.swizzle()
peo.run()
peo.perform(#selector(People.run))
}
}
extension ViewController {
func swizzle() {
let cls = People.self
let orgSel = #selector(People.run)
let newSel = #selector(runNew)
if let newMethod = class_getInstanceMethod(ViewController.self, newSel) {
let newImp = method_getImplementation(newMethod)
let type = method_getTypeEncoding(newMethod)
class_replaceMethod(cls, orgSel, newImp, type)
}
}
@objc func runNew() {
print("run new")
}
}
@objc class People: NSObject {
@objc func run() {
print("run")
}
}
直接貼出代碼運行結果:
run
run
run
run new
顯然,都是調用run方法桃犬,兩者結果是不一樣的:
peo.run() -- run
peo.perform(#selector(People.run)) -- run new
謎底是什么
Swift的默認派發(fā)機制是直接派發(fā)(Direct Dispatch)
這里是NSObject的子類刹悴,是函數(shù)表派發(fā),
ObjC的派發(fā)機制是消息機制派發(fā)(Message Dispatch),
在Swift中攒暇,這里run()走的是直接派發(fā)函數(shù)表派發(fā)土匀,而perform走的是消息機制派發(fā)。
如果要更改run()的派發(fā)方式形用,可以在run()方法前面加上dynamic
@objc dynamic func run()
就轧,這時調用run()走的是消息機制派發(fā)。
再次運行:
run
run
run new
run new
更新
除了加上dynamic的方式田度,還可以用extension妒御。extension NSObject子類的方法是消息機制派發(fā)。
extension People {
@objc func run() {
print("run")
}
}