從iOS點語法引發的一番思考

aluo 7年前發布 | 5K 次閱讀 iOS開發 移動開發

當我們去點一個屬性的時候,我們知道其實是調用了屬性的setter或者getter方法。那么,用點調用一個方法會發生什么?

這時候系統并不會崩潰,而只是報一個警告(Property access result unused)。

現在我改成用中括號正常調用方法,可是由于粗心沒有在.m中寫方法的實現,會發生什么呢?

OC是一門動態編程語言。

調用saySomething這個方法。如果這個方法只是在.h中聲明了,而沒有在.m中實現。那么我們編譯程序不會出現問題(Build Success),只有當運行程序的時候,才會直接崩潰(unrecognized selector sent to instance 0x60000000e8d0)

這是因為在編譯階段,編譯器并不知道saySomething要執行那段代碼,這個時候[people saySomething]會轉換為objc_msgSend(people, "someThing"),就是說給people以selector的形式發送someThing這個消息。當真正運行的時候,才會去people的內存中尋找someThing的地址,這時候找不到才會造成崩潰。

那么,有沒有辦法說可以不在.m中實現somtThing,而又不讓程序崩潰呢?

有!所謂 動態語言,就是一類在運行時可以改變其結構的語言:例如新的函數、對象、甚至代碼可以被引進,已有的函數可以被刪除或是其他結構上的變化。

想要程序不崩潰,我們有三次機會去拯救它。這個就是 消息轉發機制的三個步驟

第一步:動態方法解析

下圖可以看到,我沒有實現saySomething的方法,程序運行成功。實際上是調了doSomething這個方法。

我們這里的saySomething是對象方法,如果是類方法的話,對應的是resolveClassMethod:

第二步:備用接收者

如果我們浪費了第一次機會不用,還有第二次機會拯救工程:把這個消息轉給別人,讓別人替我處理!

下圖可以看到,我沒有實現run方法,而是交給了_dog去處理這個消息。在Dog.m中,我實現了的run方法被調用了!

第三步:完整轉發消息

如果我們連第二次機會都浪費了,那么還有最后一次機會補救。在完整轉發消息這一步中,我們把消息封裝到NSInvocation對象中,并把它發給一個能夠響應消息的對象。

觀察消息轉發機制的后兩步,其實都已經不是people在處理消息了,而是交給了別人。但是在外面看,我們是調用了[people run] 和 [people eat] 。通過這種方式可以將本來對象A要做的事交給B或C來做。

 

 

來自:https://segmentfault.com/a/1190000008047643

 

 本文由用戶 aluo 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!