自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

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

移動(dòng)開(kāi)發(fā)
可能大家一直看到有許多朋友在Runtime相關(guān)文章中介紹IMP指針的概念,那么IMP究竟有什么實(shí)際作用呢?

 

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

Method Swizzling

如果對(duì)Runtime有一定了解的話,一定聽(tīng)說(shuō)過(guò)或者用過(guò)這個(gè)函數(shù):

  1. 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)把自己的名字打印出來(lái),方便我去做調(diào)試或者了解項(xiàng)目結(jié)構(gòu)。

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

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

blob.png

IMP指針

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

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

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

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

  1. if !OBJC_OLD_DISPATCH_PROTOTYPES 
  2. typedef void (*IMP)(void /* id, SEL, ... */ );  
  3. else 
  4. typedef id (*IMP)(id, SEL, ...);  
  5. endif 

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

blob.png

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

blob.png

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

blob.png

blob.png

值得注意的是,如果你重寫的方法有返回值,不要忘記在***做return。

總結(jié)

實(shí)際上直接調(diào)用一個(gè)方法的IMP指針的效率是高于調(diào)用方法本身的,所以,如果你有一個(gè)合適的時(shí)機(jī)獲取到方法的IMP的話,你可以試著調(diào)用它。

這是只是IMP使用的場(chǎng)景之一,它還有許多作用,希望大家多多發(fā)現(xiàn)。

責(zé)任編輯:倪明 來(lái)源: J_雨的簡(jiǎn)書
相關(guān)推薦

2011-07-13 16:14:53

C++引用指針

2024-08-12 08:28:35

2010-01-14 10:35:34

VB.NET指針

2017-10-23 15:46:37

2022-10-30 10:24:43

Join優(yōu)化Runtime

2011-08-22 10:31:40

iPhone開(kāi)發(fā)BSD Socket

2019-08-08 08:00:00

深度學(xué)習(xí)機(jī)器學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)

2009-11-10 16:27:45

VB.NET指針

2015-03-16 10:33:14

Swift指針

2011-04-11 11:09:50

this指針

2015-01-21 16:25:29

Swift指針

2011-07-15 01:38:56

C++this指針

2017-08-28 16:01:59

前端JavaScript學(xué)習(xí)途徑

2020-05-21 08:58:34

Kubernetes操作系統(tǒng)運(yùn)維

2020-08-13 17:11:29

物聯(lián)網(wǎng)數(shù)字學(xué)習(xí)IOT

2015-12-24 09:48:40

JavaScriptthis指針深

2011-01-13 14:54:50

2020-04-28 10:28:30

Kubernetes操作系統(tǒng)運(yùn)維

2009-07-31 09:20:16

NGWS RuntimASP.NET

2021-06-10 08:51:57

C++指針聲明指針相關(guān)概念
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)