MethodSwizzle體現(xiàn)Swift與ObjC派發(fā)機制的區(qū)別

首先,實現(xiàn)一個swizzle方法替換People對象run()的IMP為runNew()的IMP,然后用兩種方式調(diào)用run(),結(jié)果會是一樣的嗎?

代碼如下:

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")
    }
}

直接貼出代碼運行結(jié)果:

run
run
run
run new

顯然,都是調(diào)用run方法,兩者結(jié)果是不一樣的:
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(),這時調(diào)用run()走的是消息機制派發(fā)。

再次運行:

run
run
run new
run new

更新

除了加上dynamic的方式,還可以用extension。extension NSObject子類的方法是消息機制派發(fā)。

extension People {
    @objc func run() {
        print("run")
    }
}

參考

深入理解 Swift 派發(fā)機制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容