Runtime之初見

人生若只如初見旋奢,何事秋風(fēng)悲畫扇。

依舊是網(wǎng)上很多runtime的資料然痊,依舊是看不懂黄绩,,玷过,這里給大家轉(zhuǎn)化一下runtime爽丹,使它由隱晦難懂變得通俗易懂。

(雖然截圖和語言組織的有些凌亂辛蚊,但是大家還是一點(diǎn)一點(diǎn)的閱讀下去吧粤蝎,可以新建一個(gè)工程,跟著我寫的一步一步的自己走一遍袋马,會(huì)有幫助的初澎。)

關(guān)于runtime理論性的東西可以參考我們同事hah的初識(shí)runtime(我倆的文章名字居然差不多)

本文參照:教你快速上手Runtime。謝謝該文作者崢吖崢老師虑凛。有興趣的也可以去崢老師的博客看看去碑宴。

另外哪里寫的不對(duì),可以給我留言桑谍,我會(huì)及時(shí)改進(jìn)的延柠,謝謝大家。

在這里我們對(duì)runtime進(jìn)行如下的介紹:

1锣披、runtime的簡單介紹

2贞间、runtime的消息發(fā)送

3贿条、用runtime交換方法

4、動(dòng)態(tài)添加方法

5增热、動(dòng)態(tài)添加屬性

6整以、runtime替換KVC,進(jìn)行字典轉(zhuǎn)換


下邊開始我們的通俗易懂的路程:

1峻仇、配置環(huán)境:新建一個(gè)工程公黑,在appdelegate里面將viewcontroller設(shè)置為rootcontroller,方便查看打印信息摄咆。

創(chuàng)建一個(gè)person類帆调,繼承自NSObject,下圖的PersonViewController無用豆同。

然后再看一下目前的工程文件結(jié)構(gòu):

按照網(wǎng)上教程我們開始runtime的各個(gè)方法的實(shí)現(xiàn)番刊。

2、發(fā)送消息影锈。舉例:實(shí)例方法和類方法的調(diào)用原理芹务。

我們建立一個(gè)繼承于NSObject的Person

在.m中分別實(shí)現(xiàn)實(shí)例方法和類方法:

然后在viewcontroller加入頭文件:#import "Person.h"、#import <objc/message.h>

方法的調(diào)用有兩種鸭廷,調(diào)用實(shí)例方法和調(diào)用類方法枣抱。我們用runtime去觀察這兩種方法的實(shí)質(zhì)。

1辆床、viewDidLoad里面實(shí)現(xiàn)Person的實(shí)例化佳晶,并用這個(gè)實(shí)例調(diào)用Person里面的實(shí)例方法;

2讼载、直接用Preson類名或類對(duì)象調(diào)用類方法轿秧。

此時(shí)我們可以看到

但是按照網(wǎng)上教程上圖藍(lán)色框框里面的也應(yīng)該可以放開注釋的,可是不知道為什么我的放開注釋以后會(huì)爆紅:

不知道是為什么(如果大家誰知道怎么回事咨堤,還煩請(qǐng)留言告訴我菇篡,再次謝謝大家了),一喘,驱还,所以這里的runtime并不友好。

哎凸克,終于知道怎么回事了议蟆,還是同事hah幫忙解決的:頭文件導(dǎo)入錯(cuò)了,應(yīng)該是導(dǎo)入:#import <objc/runtime.h>

導(dǎo)入#import<objc/messge.h>也可以調(diào)用objc_msgSend()這個(gè)方法萎战,但是不能傳參咐容,而導(dǎo)入#import<objc/runtime.h>,會(huì)出現(xiàn)這個(gè)方法:objc_msgSend(id, SEL, ...),是可以傳參數(shù)的.

在這里有的網(wǎng)友提到另外一種解決該問題的方案:謝謝北京-吳露撞鹉。方案是:引入頭文件<objc/objc-runtime>疟丙,command+點(diǎn)擊進(jìn)入這個(gè)方法颖侄,我們會(huì)看到下邊的

也就是說這個(gè)頭文件把runtime和message都包含了鸟雏,不過建議還是單獨(dú)引入享郊,因?yàn)檫@兩個(gè)頭文件里面的方法很多都類似,容易混淆孝鹊,區(qū)別在于方法是否可以傳參數(shù)炊琉。就像上邊我們舉例的問題。

打印結(jié)果:

其實(shí)這里咱們可以看到網(wǎng)上教程的注釋:不管是實(shí)例方法還是類方法又活,其本質(zhì)就是讓對(duì)象或者類對(duì)象發(fā)送消息苔咪,即我們?cè)贠C中調(diào)用的實(shí)例方法和類方法在runtime運(yùn)行時(shí)的時(shí)候?qū)嶋H上是轉(zhuǎn)化成C語言的發(fā)送消息的語句。

按照網(wǎng)上教程說的:消息機(jī)制原理:對(duì)象根據(jù)方法編號(hào)SEL去映射表查找對(duì)應(yīng)的方法實(shí)現(xiàn)

其實(shí)說的就是:找到對(duì)應(yīng)的實(shí)例方法或者類方法柳骄。

最后团赏,這里的runtime的使用并不實(shí)用

3耐薯、交換方法舔清。

其實(shí)寫完下邊的代碼,在通過理解曲初,你會(huì)發(fā)現(xiàn)這中所謂的“交換方法”實(shí)際上就是系統(tǒng)方法的重寫体谒、擴(kuò)展、再替換回去的過程臼婆。

首先我們看一下demo里面viewcontroller的結(jié)構(gòu)(同樣的personviewcontroller無用抒痒,忽略掉,這里的<objc/message.h>最好是換成#import<objc/runtime.h>):

然后我們看viewDidLoad里面颁褂,在這里我們沒有做什么操作故响,只是命名了一個(gè)image:這里我們的圖片是在工程文件中的,所以走到替換方法里面的時(shí)候會(huì)判斷不為空颁独,所以對(duì)應(yīng)的打印信息“加載空的圖片”就不會(huì)打印出來被去。

按照網(wǎng)上教程我們進(jìn)行步驟一的操作,寫一個(gè)名字叫做+ (instancetype)imageWithName:(NSString*)name的類方法奖唯。這個(gè)方法是為了替換的時(shí)候準(zhǔn)備的惨缆。

然后我們進(jìn)行步驟二,這個(gè)步驟二很關(guān)鍵丰捷,就是替換的核心所在坯墨。

注意:兩個(gè)方法。前面一個(gè)是準(zhǔn)備好的方法病往,后邊一個(gè)是系統(tǒng)的方法捣染,要用第一個(gè)方法換掉第二個(gè)方法,這里需要注意替換順序停巷。

當(dāng)我們將viewDidLoad里面的image換成一個(gè)空的圖片的時(shí)候

我們看到打印信息

是走了圖片為空的if判斷里面的耍攘。

所以榕栏,這個(gè)方法可以看成是網(wǎng)絡(luò)請(qǐng)求一張圖片,如果請(qǐng)求失敗蕾各,可以用默認(rèn)的圖片進(jìn)行展示扒磁,就像下邊的方法,網(wǎng)絡(luò)請(qǐng)求失敗的時(shí)候會(huì)展示一張默認(rèn)圖式曲。

當(dāng)然妨托,這里不是說runtime這么高大上的方法僅僅能實(shí)現(xiàn)這么low的功能,僅做示例而已吝羞。

其實(shí)這個(gè)方法替換可以用在線下替換線上代碼里面兰伤,“黑魔法”,我還不會(huì)钧排,只是聽說過敦腔。下邊繼續(xù)學(xué)習(xí)runtime其他的方法。

4恨溜、動(dòng)態(tài)添加方法符衔。

動(dòng)態(tài)添加方法,咱們的person類.h里面用到了分類:

在這里拓展一下類擴(kuò)展的知識(shí):類擴(kuò)展與分類的區(qū)別筒捺。謝謝作者:Mitchell孟晨

在這里大家是不是會(huì)想到我們的面試題中:

有的還是用英語問的:

類的作用柏腻。參考自category解析。如果大家對(duì)類別特別感興趣可以參考深入解析OC中的Category

當(dāng)我們?cè)陬愔刑砑覢interface的時(shí)候:

會(huì)出現(xiàn)上圖中的3個(gè)系吭。

第一個(gè)就是類:繼承自誰五嫂。

第二個(gè)是分類,就是分類肯尺。

類擴(kuò)展與分類的區(qū)別中有舉例說明:雖然我們?cè)诜诸愔新暶鲗傩圆粫?huì)報(bào)錯(cuò)沃缘,但是@property并沒有自動(dòng)為我們?cè)O(shè)置的屬性生成set、get方法则吟。

第三個(gè)就是extension槐臀。類擴(kuò)展。

再看上述中有一句話是這樣說的:

類擴(kuò)展的作用:

person類.m中:

viewcontroller里面:

這里沒有實(shí)現(xiàn)eat4方法氓仲,所以會(huì)在viewcontroller中的viewdidload里面調(diào)用eat4的時(shí)候水慨,會(huì)調(diào)用這個(gè)方法處理,并且把對(duì)應(yīng)的方法列表傳過來敬扛。用來判斷為實(shí)現(xiàn)的方法是不是我們想要?jiǎng)討B(tài)添加的方法晰洒。

這里注意的是,崢老師教程里面在調(diào)用class_addMethod(self,@selector(eat4), (IMP)eatt,"v@:");這個(gè)方法的時(shí)候啥箭,第三個(gè)參數(shù)前面并沒有添加“(IMP)”谍珊,不添加這個(gè)IMP,會(huì)報(bào)黃:

說的什么不清楚急侥,意思就是叫你添加上IMP砌滞。

拓展一下performSelector調(diào)用和直接調(diào)用的區(qū)別:

準(zhǔn)備好了侮邀,我們看打印結(jié)果:

這里我們可以看到NSStringFromSelector(sel)調(diào)用的就是eat4。

扯了這么多怎么用贝润,到底這個(gè)動(dòng)態(tài)添加方法到底是用來干什么的呢绊茧,看看眾多網(wǎng)友的理解。翻了好多题暖,就下邊的兩個(gè)解釋比較靠譜按傅,大家湊合著看吧:

當(dāng)然還有最一開始咱們引入動(dòng)態(tài)添加的時(shí)候的目的:

不忘初心捉超,方得始終胧卤。

5、動(dòng)態(tài)添加屬性拼岳。

想知道原理的請(qǐng)移步OC Associated Objects實(shí)現(xiàn)原理

原理:給一個(gè)類聲明屬性枝誊,其實(shí)本質(zhì)就是給這個(gè)類添加關(guān)聯(lián),并不是直接把這個(gè)值的內(nèi)存空間添加到類存空間惜纸。

看結(jié)構(gòu)叶撒,添加了一個(gè)NSObject的分類:

分類的.h文件,將set方法和name外漏耐版,方便在viewcontroller里面調(diào)用祠够。

分類的.m文件,set方法和name的實(shí)現(xiàn)粪牲。

最后看viewcontroller里面古瓤,引入分類的頭文件,然后實(shí)例化NSObject腺阳,調(diào)用objc1的name落君。

最后的打印結(jié)果:

tips:其實(shí)呢這個(gè)動(dòng)態(tài)添加屬性,是在哪里用到的呢亭引?具體的我也說不上來绎速。其實(shí)按照我的理解,咱們這里所謂的動(dòng)態(tài)添加屬性焙蚓,是在分類上邊添加的屬性纹冤,那么我就想了,為什么我不能在類自己本身上邊添加屬性呢购公?對(duì)吧萌京?為什么非要在分類上邊添加呢,還整了個(gè)動(dòng)態(tài)添加屬性君丁,麻煩不枫夺?!原因有兩個(gè):

1)如果你的類自己本身里面的邏輯或者代碼比較多绘闷,而需求是新加一個(gè)功能橡庞,那么就可以在分類上邊添加较坛,因?yàn)榉诸惡屠^承還是有區(qū)別的。咱們這樣理解鞍亲睢:如果你用的是繼承丑勤,那么在子類a里面新添加的屬性和方法,在父類以及其他繼承父類的子類b里面是不能用新添加的屬性和方法的吧趣,(有點(diǎn)繞)法竞。但是分類就行,你在分類里面新添加了屬性和方法强挫,那么在其他用到這個(gè)類自己的地方岔霸,是可以用新添加的屬性和方法的。好像和公有性俯渤、私有性有點(diǎn)關(guān)系呆细。

2)給系統(tǒng)的類添加屬性。像UIView八匠、UIImageView絮爷、UILabel、UIButton等等系統(tǒng)的類梨树,你覺得系統(tǒng)的類里面的屬性不夠用(當(dāng)然坑夯,像我這種小白還是覺得夠用的,關(guān)鍵不知道各個(gè)類里面除了經(jīng)常用的還有啥抡四,柜蜈,,)就可以自己添加屬性床嫌,當(dāng)然了跨释,在MJ和SDWebimage里面其實(shí)也能看到動(dòng)態(tài)添加屬性的影子,只不過是我們大多數(shù)人沒有進(jìn)入人家里面去看具體的代碼厌处。同事hah在runtime初識(shí)里面也提到了這個(gè):

6鳖谈、字典轉(zhuǎn)模型

崢老師說的“字典轉(zhuǎn)模型的方式一:KVC”這個(gè)就是咱們平時(shí)JSON解析的時(shí)候經(jīng)常用到的,這里不作進(jìn)一步解釋阔涉,看看崢老師說的用runtime字典轉(zhuǎn)模型的方式缆娃。

沒搞明白。瑰排。贯要。

先用KVC吧。




總的來說椭住,即便咱們知道了runtime是怎么用的崇渗,但是沒有合適的環(huán)境使用runtime,也是白搭。所以宅广,咱們現(xiàn)在能做的就是先了解runtime葫掉,隨時(shí)記在心中,以后哪里能夠用到的跟狱,可以嘗試著用runtime的特性和上述幾個(gè)方法來實(shí)現(xiàn)俭厚,甚至于用runtime解決bug。

另外這里有很多關(guān)于runtime的集合驶臊,大家可以參考:runtime專題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末挪挤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子关翎,更是在濱河造成了極大的恐慌扛门,老刑警劉巖背桐,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異形真,居然都是意外死亡捞稿,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門六孵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事闹啦。” “怎么了辕坝?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵窍奋,是天一觀的道長。 經(jīng)常有香客問我酱畅,道長琳袄,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任纺酸,我火速辦了婚禮窖逗,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘餐蔬。我一直安慰自己碎紊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布樊诺。 她就那樣靜靜地躺著仗考,像睡著了一般。 火紅的嫁衣襯著肌膚如雪词爬。 梳的紋絲不亂的頭發(fā)上秃嗜,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼锅锨。 笑死螺句,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的橡类。 我是一名探鬼主播蛇尚,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼顾画!你這毒婦竟也來了取劫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤研侣,失蹤者是張志新(化名)和其女友劉穎谱邪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庶诡,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡惦银,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了末誓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扯俱。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖喇澡,靈堂內(nèi)的尸體忽然破棺而出迅栅,到底是詐尸還是另有隱情,我是刑警寧澤晴玖,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布读存,位于F島的核電站,受9級(jí)特大地震影響呕屎,放射性物質(zhì)發(fā)生泄漏让簿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一秀睛、第九天 我趴在偏房一處隱蔽的房頂上張望尔当。 院中可真熱鬧,春花似錦琅催、人聲如沸居凶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侠碧。三九已至,卻和暖如春缠黍,著一層夾襖步出監(jiān)牢的瞬間弄兜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留替饿,地道東北人语泽。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像视卢,于是被迫代替她去往敵國和親踱卵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉据过,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,715評(píng)論 0 9
  • 對(duì)于從事 iOS 開發(fā)人員來說惋砂,所有的人都會(huì)答出【runtime 是運(yùn)行時(shí)】什么情況下用runtime?大部分人能...
    夢夜繁星閱讀 3,721評(píng)論 7 64
  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,557評(píng)論 33 466
  • Runtime是什么 Runtime 又叫運(yùn)行時(shí),是一套底層的 C 語言 API绳锅,其為 iOS 內(nèi)部的核心之一西饵,我...
    SuAdrenine閱讀 877評(píng)論 0 3
  • 【摩篇第八】(8.3)其摩者,有以平鳞芙、有以正眷柔,有以喜,有以怒原朝,有以名驯嘱,有以行,有以廉竿拆,有以信宙拉,有以利,有以卑丙笋。平者...
    海納百川vs王者之風(fēng)閱讀 315評(píng)論 0 0