前言嘮嘮嗑
前一段時(shí)間和大神們聊天,都在談?wù)搑untime,然后我就一臉蒙逼了,只能不好意思的捂著眼睛聽(tīng)他們?cè)谫?。so,還是決定不能太丟人哈,這種裝逼神級(jí)咱們也要掌握一下。一直有聽(tīng)到runtime這個(gè)詞,總感覺(jué)高高在上,其實(shí)靜下心來(lái),也是挺好理解的。然后我就分享一下我的學(xué)習(xí)心得,供大家從0到1的掌握這門(mén)技巧。

一、什么是runtime?
不用什么大理論解釋了,純腦動(dòng)講解。RunTime簡(jiǎn)稱(chēng)運(yùn)行時(shí),這時(shí)候有心的同學(xué)就會(huì)說(shuō)了,OC就是運(yùn)行時(shí)機(jī)制,答對(duì)!其實(shí)runtime也就是在運(yùn)行時(shí)候的一些機(jī)制,我們用到最多的就是消息機(jī)制。 runtime是一套比較底層的純C語(yǔ)言API, 屬于1個(gè)C語(yǔ)言庫(kù), 包含了很多底層的C語(yǔ)言API。 在我們平時(shí)編寫(xiě)的OC代碼中, 程序運(yùn)行過(guò)程時(shí), 其實(shí)最終都是轉(zhuǎn)成了runtime的C語(yǔ)言代碼, runtime算是OC的幕后工作者。
舉例說(shuō)明一下
OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend("MJPerson" , "alloc"), "init")
二:runtime可以干什么?
- 在程序運(yùn)行過(guò)程中,動(dòng)態(tài)創(chuàng)建一個(gè)類(lèi)。(例如KVO的底層)
- 在程序運(yùn)行過(guò)程中, 動(dòng)態(tài)地為某個(gè)類(lèi)添加屬性\方法, 修改屬性值\方法
- 遍歷一個(gè)類(lèi)的所有成員變量(屬性)\所有方法
三:怎么和runtime交互?
OC中有三種與runtime交互的級(jí)別,分別是:
- 通過(guò) Objective-C 源代碼
- 通過(guò) Foundation 庫(kù)中定義的 NSObject 提供的方法
- 通過(guò)直接調(diào)用 runtime 方法
四:簡(jiǎn)單使用準(zhǔn)備
1.通過(guò)OC源代碼
在大多數(shù)的部分,運(yùn)行時(shí)系統(tǒng)會(huì)自動(dòng)運(yùn)行并在后臺(tái)運(yùn)行。我們使用它只是寫(xiě)源代碼并編譯源代碼。當(dāng)編譯包含 Objective-C 類(lèi)和方法的代碼時(shí),編譯器會(huì)創(chuàng)建實(shí)現(xiàn)了語(yǔ)言動(dòng)態(tài)特性的數(shù)據(jù)結(jié)構(gòu)和函數(shù)調(diào)用。該數(shù)據(jù)結(jié)構(gòu)捕獲在類(lèi)、擴(kuò)展和協(xié)議中所定義的信息。
最重要的 runtime 函數(shù)是發(fā)消息函數(shù),在編譯時(shí),編譯器會(huì)轉(zhuǎn)換成類(lèi)似 objc_msgSend 這樣的發(fā)送消息的函數(shù)。因此,我們通過(guò)寫(xiě)好源代碼,編譯器會(huì)自動(dòng)幫助我們編譯成 runtime 代碼。
(有些人可能說(shuō),我這說(shuō)了段廢話。不過(guò),非也,知其然要知其所以然,本文就是介紹理論滴。。)
2.通過(guò)NSObject提供的方法
在 Cocoa 編程中,大部分的類(lèi)都繼承于 NSObject ,有些 NSObject 提供的方法僅僅是為了查詢(xún)運(yùn)動(dòng)時(shí)系統(tǒng)的相關(guān)信息,這此方法都可以反查自己。比如 -isKindOfClass: 和 -isMemberOfClass: 都是用于查詢(xún)?cè)诶^承體系中的位置。 -respondsToSelector: 指明是否接受特定的消息。 +conformsToProtocol: 指明是否要求實(shí)現(xiàn)在指定的協(xié)議中聲明的方法。 -methodForSelector: 提供方法實(shí)現(xiàn)的地址。
3.通過(guò)直接調(diào)用runtime函數(shù)
我們需要用到這兩個(gè)頭文件:
#import <objc/runtime.h>
#import <objc/objc.h>
舉例子簡(jiǎn)單說(shuō)明
發(fā)送消息
方法調(diào)用的本質(zhì),就是讓對(duì)象發(fā)送消息。objc_msgSend,只有對(duì)象才能發(fā)送消息,因此以objc開(kāi)頭。
// 創(chuàng)建person對(duì)象
Person *p = [[Person alloc] init];
// 調(diào)用對(duì)象方法
[p eat]
// 本質(zhì):讓對(duì)象發(fā)送消息
objc_msgSend(p, @selector(eat));
// 調(diào)用類(lèi)方法的方式:兩種
// 第一種通過(guò)類(lèi)名調(diào)用
[Person eat];
// 第二種通過(guò)類(lèi)對(duì)象調(diào)用
[[Person class] eat];
// 用類(lèi)名調(diào)用類(lèi)方法,底層會(huì)自動(dòng)把類(lèi)名轉(zhuǎn)換成類(lèi)對(duì)象調(diào)用
// 本質(zhì):讓類(lèi)對(duì)象發(fā)送消息
objc_msgSend([Person class], @selector(eat));
結(jié)語(yǔ)
理論知識(shí)難免枯燥乏味,但是只要掌握這門(mén)技術(shù)就一定要知其所以然,才能有長(zhǎng)遠(yuǎn)的發(fā)展。今天先介紹下理論,很快將會(huì)發(fā)進(jìn)階篇,說(shuō)說(shuō)具體怎么應(yīng)用。希望我的小小文字可以幫助你進(jìn)步一點(diǎn),謝謝支持。