前話
這段時間學(xué)習(xí) Runtime,網(wǎng)上看了一些文章,這里整理一下,給準(zhǔn)備學(xué) Runtime 的朋友一個參考.希望大家可以看完'前話'-----'Demo 下載'小節(jié),再去看提到的文章.
Runtime 中最重要的就是消息機制
.
參考
如這里邊很多文章的作者提到的那樣, Runtime 文章網(wǎng)上很多,但不是每一篇我們新手都能看懂,有一些直接堆積概念,作為初學(xué)的我們,肯定滿頭霧水. 學(xué)習(xí)一個陌生的東西,我覺得我們學(xué)習(xí)的路徑,最好是先對其的概念有個很簡單淺顯的理解,然后仿照寫幾個 Demo,消除陌生感后,我們再深入的了解一下實現(xiàn)機制和具體方法的含義.
我第一篇看的文章 《OC最實用的runtime總結(jié)悼沈,面試弓叛、工作你看我就足夠了!》,這篇文章很淺顯,很易懂.跟著寫完里邊所有提到的案例之后,發(fā)現(xiàn) Runtime 并沒有半年前在網(wǎng)上打算學(xué)習(xí)看的那篇冗余的文章的所伴隨的滿頭霧水.基本上對 Runtime 的基本方法有了一個具體的了解.
從這里,我們總結(jié)出 Runtime 的一些基本的函數(shù)方法,如下
獲得某個類的類方法
Method class_getClassMethod(Class cls , SEL name)
獲得某個類的實例對象方法
Method class_getInstanceMethod(Class cls , SEL name)
交換兩個方法的實現(xiàn)
void method_exchangeImplementations(Method m1 , Method m2)
set方法,將值value 跟對象object 關(guān)聯(lián)起來(將值value 存儲到對象object 中) 參數(shù) object:給哪個對象設(shè)置屬性 參數(shù) key:一個屬性對應(yīng)一個Key革屠,將來可以通過key取出這個存儲的值,key 可以是任何類型:double、int 等,建議用char 可以節(jié)省字節(jié) 參數(shù) value:給屬性設(shè)置的值 參數(shù)policy:存儲策略 (assign 亚茬、copy 、 retain就是strong)
void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)
利用參數(shù)key 將對象object中存儲的對應(yīng)值取出來
id objc_getAssociatedObject(id object , const void *key)
獲得某個類的所有成員變量(outCount 會返回成員變量的總數(shù)) 參數(shù): 1浓恳、哪個類 2刹缝、放一個接收值的地址,用來存放屬性的個數(shù) 3颈将、返回值:存放所有獲取到的屬性梢夯,通過下面兩個方法可以調(diào)出名字和類型Ivar *class_copyIvarList(Class cls , unsigned int *outCount)
獲得成員變量的名字
const char *ivar_getName(Ivar v)
獲得成員變量的類型
const char *ivar_getTypeEndcoding(Ivar v)
獲取協(xié)議列表
protocol_getName
獲取屬性列表
property_getName
文/滕先洪(簡書作者) 原文鏈接:http://www.reibang.com/p/ab966e8a82e2 著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)晴圾,并標(biāo)注“簡書作者”颂砸。
然后,在 Swift 第一屆參會群里,看到正好有人討論 Runtime,有人截圖在百度搜索靠前的這篇文章 《Runtime 10種用法(沒有比這更全的了)》,名字有點夸張,但是相信作者把文章中提到的幾個篇文章都已經(jīng)看了一遍.如果我們把這些文章看一遍的話,基本對 Runtime 能夠有個大概的了解了.而且這篇文章中,作者對幾篇文章做了一個簡單的概括.
從這里我們得出, Runtime的簡單實用場景:
- 動態(tài)交換兩個方法的實現(xiàn)(Swizzle 黑魔法)
- 攔截交換系統(tǒng)自帶的方法(Swizzle 黑魔法)
- 動態(tài)給分類的成員變量和成員方法
- 給分類增加屬性
- 獲得一個類的所有成員變量
- 獲取一個類的類方法,對象方法
- 字典轉(zhuǎn)模型,MJExtesion和 YYModel的基本實現(xiàn)原理
- 動態(tài)添加方法 performSelector
- 實現(xiàn)NSCoding的自動歸檔和自動解檔
- 在方法上增加額外功能
- 動態(tài)更改變量的值
《Runtime 10種用法(沒有比這更全的了)》這篇文章里提到了上邊《OC最實用的runtime總結(jié),面試、工作你看我就足夠了沾凄!》這篇文章,除了這篇文章,還有《讓你快速上手Runtime》,小碼哥袁錚寫的.
《runtime詳解》這篇文章除了我們上邊提到的幾個基本用法之外,我們主要在這篇文章中查看幾個參數(shù)的概念:
- objc_msgSend
- SEL
- id
- Class
- Method
- IMP
- Cache
- Property
《詳解runtime運行時機制 》其中也有對參數(shù)的解析(和上一篇有重復(fù)),另外這篇文章,適合我們在基本掌握了前邊 Runtime 的使用方法之后,想要對很多概念更加深入了解的訴求.比如:Method和IMP
除了上述幾篇文章,在方法替換的時候,為了比較方法替換兩種寫法的區(qū)別,我還閱讀了《Objective-C的方法替換》這篇文章
Runtime消息機制
如同最開始上邊說的那樣梗醇,Runtime最重要的就是消息機制,了解消息機制撒蟀,查看蘋果開源的實現(xiàn)源碼,會讓我們更加了解蘋果針對Object-C語言的用心和強大温鸽。這篇文章《runtime-消息機制》推薦給大家保屯,期間有些地方我也沒有看懂,作者自己也說了涤垫,為了寫這篇文章姑尺,看蘋果源碼頭都大了。我們又不是天才蝠猬,怎么可能隨隨便便就懂得切蟋。好在有人給我們整理了這些,我們站在巨人的肩膀上榆芦,再看源碼即使有不清楚的地方柄粹,也有參考和指導(dǎo)。
還有該作者的另一篇文章《runtime-屬性與變量》匆绣,寫的很用心驻右。
實戰(zhàn)
在實際項目過程中,我遇到下邊情況,我們都可以用Runtime完成:
- 實現(xiàn)萬能控制器跳轉(zhuǎn)《iOS 萬能跳轉(zhuǎn)界面方法 (runtime實用篇一))》
- 還有就是檢測用戶上網(wǎng)時候準(zhǔn)確使用了多少數(shù)據(jù)流量.這對于現(xiàn)在 QQ, 網(wǎng)易云音樂贈送用戶數(shù)據(jù)流量的統(tǒng)計十分重要
- 適配iOS時,我們有時候不同系統(tǒng)版本的手機的iOS所用到的圖片素材不一樣,也可以用運行時輕松完成.這個實例在提到的文章中還有我的Demo代碼下載中都有寫出.
其它
在閱讀 Runtime文章的時候,我還對元類和超類的概念比較的模糊.超類其實就是我們在翻譯的時候,對 super class 的另一種翻譯法,我們一般叫他'父類',這樣也更加容易理解. 元類可以讀《Objective-C 中的元類(meta class)是什么?》這篇文章.我們首先搞清楚對象和類的數(shù)據(jù)結(jié)構(gòu),更加有助于理解. 加單來說元類就是類的類,而元類的類叫做根元類.以此類推,所有的元類使用根元類作為他們的類崎淳,根元類的元類則就是它自己堪夭。也就是說基類的元類的isa指針指向他自己。
Demo 下載
我已經(jīng)對上邊的 Runtime 的大部分代碼進(jìn)行了梳理,需要的可以點過來Demo 鏈接
文章段落摘要
(如有侵權(quán),請聯(lián)系我,立刻刪除)
1.. 還有一些 NSObject 的方法可以從 Runtime 系統(tǒng)中獲取信息拣凹,允許對象進(jìn)行自我檢查森爽。例如: - class方法返回對象的類; - isKindOfClass: 和 -isMemberOfClass: 方法檢查對象是否存在于指定的類的繼承體系中(是否是其子類或者父類或者當(dāng)前類的成員變量)嚣镜; - respondsToSelector: 檢查對象能否響應(yīng)指定的消息爬迟; - conformsToProtocol:檢查對象是否實現(xiàn)了指定協(xié)議類的方法; - methodForSelector: 返回指定方法實現(xiàn)的地址祈惶。 文/Ammar(簡書作者)
原文鏈接:http://www.reibang.com/p/1e06bfee99d0
著作權(quán)歸作者所有雕旨,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”捧请。
2.. 值得注意的時凡涩,objc_class 中也有一個 isa 指針,這說明 Objc 類本身也是一個對象疹蛉。為了處理類和對象的關(guān)系蹋偏,Runtime 庫創(chuàng)建了一種叫做 Meta Class(元類) 的東西,類對象所屬的類就叫做元類磁滚。Meta Class 表述了類對象本身所具備的元數(shù)據(jù)。 我們所熟悉的類方法克蚂,就源自于 Meta Class。我們可以理解為類方法就是類對象的實例方法筋讨。每個類僅有一個類對象埃叭,而每個類對象僅有一個與之相關(guān)的元類。 當(dāng)你發(fā)出一個類似 NSObject alloc 的消息時悉罕,實際上赤屋,這個消息被發(fā)送給了一個類對象(Class Object),這個類對象必須是一個元類的實例壁袄,而這個元類同時也是一個根元類(Root Meta Class)的實例类早。所有元類的 isa 指針最終都指向根元類。 所以當(dāng) [NSObject alloc] 這條消息發(fā)送給類對象的時候嗜逻,運行時代碼 objc_msgSend() 會去它元類中查找能夠響應(yīng)消息的方法實現(xiàn)涩僻,如果找到了,就會對這個類對象執(zhí)行方法調(diào)用栈顷。
上圖實現(xiàn)是 super_class 指針逆日,虛線時 isa 指針。而根元類的父類是 NSObject 妨蛹,isa 指向了自己屏富。而 NSObject 沒有父類。 最后 objc_class 中還有一個 objc_cache 蛙卤,緩存狠半,它的作用很重要,后面會提到颤难。
文/Ammar(簡書作者) 原文鏈接:http://www.reibang.com/p/1e06bfee99d0
著作權(quán)歸作者所有神年,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),并標(biāo)注“簡書作者”行嗤。
3.. 獲取方法地址 NSObject 類中有一個實例方法:methodForSelector 已日, 你可以用它來獲取某個方法選擇器對應(yīng)的 IMP ,舉個例子: void (setter)(id, SEL, BOOL); int i; setter = (void ()(id, SEL, BOOL))[target methodForSelector:@selector(setFilled:)]; for ( i = 0 ; i < 1000 ; i++ ) setter(targetList[i], @selector(setFilled:), YES);
當(dāng)方法被當(dāng)做函數(shù)調(diào)用時栅屏,兩個隱藏參數(shù)也必須明確給出飘千,上面的例子調(diào)用了1000次函數(shù),你也可以嘗試給 target 發(fā)送1000次 setFilled: 消息會花多久栈雳。 雖然可以更高效的調(diào)用方法护奈,但是這種做法很少用,除非時需要持續(xù)大量重復(fù)調(diào)用某個方法的情況哥纫,才會選擇使用以免消息發(fā)送泛濫霉旗。 注意: methodForSelector: 方法是由 Runtime 系統(tǒng)提供的,而不是 Objc 自身的特性
文/Ammar(簡書作者) 原文鏈接:http://www.reibang.com/p/1e06bfee99d0
著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)厌秒,并標(biāo)注“簡書作者”读拆。
4.. 動態(tài)綁定所做的,即是在實例所屬類確定后鸵闪,將某些屬性和相應(yīng)的方法綁定到實例上檐晕。這里所指的屬性和方法當(dāng)然包括了原來沒有在類中實現(xiàn)的,而是在運行時才需要的新加入的實現(xiàn)蚌讼。**在Cocoa層棉姐,我們一般向一個NSObject對象發(fā)送-respondsToSelector:或者-instancesRespondToSelector:等來確定對象是否可以對某個SEL做出響應(yīng),而在OC消息轉(zhuǎn)發(fā)機制被觸發(fā)之前啦逆,對應(yīng)的類的+resolveClassMethod:和+resolveInstanceMethod:將會被調(diào)用,
**在此時有機會動態(tài)地向類或者實例添加新的方法笛洛,也即類的實現(xiàn)是可以動態(tài)綁定的夏志。
文/Onevcat(簡書作者) 原文鏈接:https://onevcat.com/2012/04/objective-c-runtime/
著作權(quán)歸作者所有,轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)苛让,并標(biāo)注“作者”沟蔑。
參考文章
- 《OC最實用的runtime總結(jié),面試狱杰、工作你看我就足夠了瘦材!》
- 《Objective-C的方法替換》
- 《Runtime 10種用法(沒有比這更全的了)》
- 《IOS SEL (@selector) 原理及使用總結(jié)(一)》
- 《iOS 萬能跳轉(zhuǎn)界面方法 (runtime實用篇一))》
- 《詳解runtime運行時機制 》
- 《runtime詳解》
- 《Runtime 10種用法(沒有比這更全的了)》
- 《讓你快速上手Runtime》
- 《官方維護(hù)的 Demo》
- 《貓神提到的 Runtime》
- 《runtime-消息機制》
- 《runtime-屬性與變量》
交流
希望能和大家交流技術(shù)
我的博客地址: http://www.lilongcnc.cc/