輕松學(xué)習(xí)之三——IMP指針的作用

可能大家一直看到有許多朋友在Runtime相關(guān)文章中介紹IMP指針的概念淌铐,那么IMP究竟有什么實(shí)際作用呢?讓我們先從一個(gè)函數(shù)看起來蔫缸。

Method Swizzling

如果對(duì)Runtime有一定了解的話腿准,一定聽說過或者用過這個(gè)函數(shù):

void method_exchangeImplementations(Method m1, Method m2)

它通常叫做method swizzling,算是ObjC的"黑魔法"了捂龄,作用就是在程序運(yùn)行期間動(dòng)態(tài)的給兩個(gè)方法互換實(shí)現(xiàn)释涛,比如有這樣一種使用場(chǎng)景:


我們的程序中有許多個(gè)ViewController,我想在對(duì)項(xiàng)目改動(dòng)最小的情況下倦沧,在當(dāng)每個(gè)Controller執(zhí)行完ViewDidLoad以后就在控制臺(tái)把自己的名字打印出來唇撬,方便我去做調(diào)試或者了解項(xiàng)目結(jié)構(gòu)。


有許多朋友會(huì)這樣說展融,讓所有控制器都繼承一個(gè)BaseController不就可以了嗎窖认?我在這里要解釋一下這樣做的缺點(diǎn):假如你的項(xiàng)目里有許多Controller的話,你就需要把項(xiàng)目里凡是沒有繼承自BaseController的每個(gè)Controller都做一次修改了,而且隨意更改層級(jí)結(jié)構(gòu)會(huì)發(fā)生意想不到的錯(cuò)誤扑浸。

其實(shí)我們的目的就是重寫ViewDidLoad的方法烧给,并在他的方法最后加上幾句Log,所以我們需要給UIViewController建立一個(gè)category喝噪,因?yàn)槲覀冎来〉眨绻贑atagory中重寫一個(gè)方法,就會(huì)覆蓋它的原有方法實(shí)現(xiàn)酝惧,但是榴鼎,這樣做以后就沒有辦法調(diào)用系統(tǒng)原有的方法,因?yàn)樵谝粋€(gè)方法里調(diào)用自己的方法會(huì)是一個(gè)死循環(huán)晚唇。所以我們的解決辦法就是巫财,另外寫一個(gè)方法來和viewDidLoad“交換”,這樣外部調(diào)用viewDidLoad就會(huì)調(diào)到新建的這個(gè)方法中哩陕,同樣平项,我們調(diào)用新建的方法就會(huì)調(diào)用到系統(tǒng)的viewDidLoad中了。

Screen Shot 2015-07-15 at 11.10.02 AM.png

IMP指針

其實(shí)悍及,還有一種更加簡(jiǎn)單的方法可以讓我們辦到相同的目的闽瓢,運(yùn)用IMP指針,IMP就是Implementation的縮寫并鸵,顧名思義鸳粉,它是指向一個(gè)方法實(shí)現(xiàn)的指針,每一個(gè)方法都有一個(gè)對(duì)應(yīng)的IMP园担,所以届谈,我們可以直接調(diào)用方法的IMP指針,來避免方法調(diào)用死循環(huán)的問題弯汰。

調(diào)用一個(gè)IMP的方式和調(diào)用普通C函數(shù)相同艰山,比如:

id returnObjc = someIMP(objc,SEL,params...);

不過如果你的項(xiàng)目沒有做其他配置的話這樣調(diào)用編譯器是不會(huì)通過的,我們來看一下先它的定義:

if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
else
typedef id (*IMP)(id, SEL, ...); 
endif

在默認(rèn)情況下你的工程是打開這個(gè)配置的

Screen Shot 2015-07-15 at 2.29.56 PM.png

這種情況下IMP被定義為無參數(shù)無返回值的函數(shù)咏闪。所以你需要到工程里搜索到這個(gè)選項(xiàng)并把它關(guān)閉曙搬。這樣的麻煩就是,每次使用鸽嫂,你都需要修改工程配置纵装,所以這里我再介紹另外一種辦法:重新定義一個(gè)和有參數(shù)的IMP指針相同的指針類型,在獲取IMP時(shí)把它強(qiáng)轉(zhuǎn)為此類型据某。這樣運(yùn)用IMP指針后橡娄,就不需要額外的給ViewController寫新的方法:

Screen Shot 2015-07-16 at 9.56.19 AM.png

還有一個(gè)地方我們需要注意,如果這樣直接調(diào)用IMP的話就會(huì)發(fā)生經(jīng)典的EXC_BAD_ACCESS錯(cuò)誤癣籽,我們定義的IMP指針是一個(gè)有返回值的類型挽唉,而其實(shí)我們獲取的viewDidLoad這個(gè)方法是沒有返回值的滤祖,所以我們需要新定義一個(gè)和IMP相同類型的函數(shù)指針比如VIMP,把他的返回值定位Void瓶籽,這樣如果你修改的方法有返回值就用IMP匠童,沒有返回值就用VIMP。

Screen Shot 2015-07-15 at 5.49.54 PM.png
Screen Shot 2015-07-15 at 3.36.05 PM.png

值得注意的是塑顺,如果你重寫的方法有返回值汤求,不要忘記在最后做return。

總結(jié)

實(shí)際上直接調(diào)用一個(gè)方法的IMP指針的效率是高于調(diào)用方法本身的严拒,所以首昔,如果你有一個(gè)合適的時(shí)機(jī)獲取到方法的IMP的話,你可以試著調(diào)用它糙俗。
這是只是IMP使用的場(chǎng)景之一,它還有許多作用预鬓,希望大家多多發(fā)現(xiàn)巧骚。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市格二,隨后出現(xiàn)的幾起案子劈彪,更是在濱河造成了極大的恐慌,老刑警劉巖顶猜,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沧奴,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡长窄,警方通過查閱死者的電腦和手機(jī)滔吠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挠日,“玉大人疮绷,你說我怎么就攤上這事∠保” “怎么了冬骚?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)懂算。 經(jīng)常有香客問我只冻,道長(zhǎng),這世上最難降的妖魔是什么计技? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任喜德,我火速辦了婚禮,結(jié)果婚禮上酸役,老公的妹妹穿的比我還像新娘住诸。我一直安慰自己驾胆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布贱呐。 她就那樣靜靜地躺著丧诺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奄薇。 梳的紋絲不亂的頭發(fā)上驳阎,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音馁蒂,去河邊找鬼呵晚。 笑死,一個(gè)胖子當(dāng)著我的面吹牛沫屡,可吹牛的內(nèi)容都是我干的饵隙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼沮脖,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼金矛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勺届,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤驶俊,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后免姿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體饼酿,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年胚膊,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了故俐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡澜掩,死狀恐怖购披,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情肩榕,我是刑警寧澤刚陡,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站株汉,受9級(jí)特大地震影響筐乳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乔妈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一蝙云、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧路召,春花似錦勃刨、人聲如沸波材。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽廷区。三九已至,卻和暖如春贾铝,著一層夾襖步出監(jiān)牢的瞬間隙轻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工垢揩, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留玖绿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓叁巨,卻偏偏與公主長(zhǎng)得像斑匪,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子锋勺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉秤标,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,679評(píng)論 0 9
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,544評(píng)論 33 466
  • 繼上Runtime梳理(四) 通過前面的學(xué)習(xí),我們了解到Objective-C的動(dòng)態(tài)特性:Objective-C不...
    小名一峰閱讀 741評(píng)論 0 3
  • __block和__weak修飾符的區(qū)別其實(shí)是挺明顯的:1.__block不管是ARC還是MRC模式下都可以使用宙刘,...
    LZM輪回閱讀 3,284評(píng)論 0 6
  • 1.寫一個(gè)NSString類的實(shí)現(xiàn) +(id)initWithCString:(c*****t char *)nu...
    韓七夏閱讀 3,747評(píng)論 2 37