Runtime筆記

一、runtime簡介

  • Runtime簡稱運行時。OC就是運行時機(jī)制, 也就是在運行時候的一些機(jī)制, 其中最主要的是消息機(jī)制。
  • 對于C語言,函數(shù)的調(diào)用在編譯的時候就會決定調(diào)用哪個函數(shù)爪幻。
  • 對于OC的函數(shù)掌挚,屬于動態(tài)調(diào)用過程业踢,在編譯的時候并不能決定真正調(diào)用哪個函數(shù)届慈,只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應(yīng)函數(shù)來調(diào)用截碴。
  • 事實證明:
  • 在編譯階段孔庭,OC可以調(diào)用任何函數(shù)尺上,及時這個函數(shù)并未實現(xiàn)材蛛,只要聲明過就不會報錯。
  • 在編譯階段怎抛,C語言調(diào)用未實現(xiàn)函數(shù)就會報錯卑吭。

二、runtime使用

1.發(fā)送消息

  • 方法調(diào)用的本質(zhì)马绝,就是讓對象發(fā)送消息豆赏。
  • objc_msgSend,只有對象才能發(fā)送消息富稻,因此以objc開頭掷邦。
  • 使用消息機(jī)制前提,必須導(dǎo)入#import<objc/message.h>
  • 消息機(jī)制的簡單使用
// 創(chuàng)建person對象
Person *p = [[Person alloc] init];

// 調(diào)用對象方法
[p eat];

// 給對象發(fā)送消息
objc_msgSend(p, @selector(eat));

// 調(diào)用類方法的方式:兩種
// 第一種:通過類名調(diào)用
[Person eat];
// 第二種:通過類對象調(diào)用
[[Person class] eat];

// 用類名調(diào)用類的方法椭赋,底層會自動把類名轉(zhuǎn)換成類對象調(diào)用
// 本質(zhì):給類對象發(fā)送消息
objc_msgSend([Person class], @selector(eat));
  • 消息機(jī)制原理:對象根據(jù)方法編號SEL去映射表查找對應(yīng)實現(xiàn)


    消息機(jī)制原理

2.交換方法 (method swizzling---移魂大法)

  • 開發(fā)使用場景:系統(tǒng)自帶的方法不夠用抚岗,給系統(tǒng)自帶的方法擴(kuò)展一些功能,并且保持原有的功能纹份。
  • 方式一:繼承系統(tǒng)的類苟跪,重寫方法。
  • 方法二:使用runtime蔓涧,交換方法件已。
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 需求:給imageNamed方法提供功能,每次加載圖片就判斷下圖片是否加載成功元暴。
    // 步驟一:先搞個分類篷扩,定義一個能加載圖片并且能打印的方法+ (instancetype)imageWithName:(NSString *)name;
    // 步驟二:交換imageNamed和imageWithName的實現(xiàn),就能調(diào)用imageWithName茉盏,間接調(diào)用imageWithName的實現(xiàn)鉴未。
    UIImage *image = [UIImage imageNamed:@"123"];
}

@end

@implementation UIImage (Image)
// 加載分類到內(nèi)存的時候調(diào)用
+ (void)load
{
    // 交換方法

    // 獲取imageWithName方法地址
    Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));

    // 獲取imageWithName方法地址
    Method imageName = class_getClassMethod(self, @selector(imageNamed:));

    // 交換方法地址,相當(dāng)于交換實現(xiàn)方式
    method_exchangeImplementations(imageWithName, imageName);
}

// 不能在分類中重寫系統(tǒng)方法imageNamed鸠姨,因為會把系統(tǒng)的功能給覆蓋掉铜秆,而且分類中不能調(diào)用super.

// 既能加載圖片又能打印
+ (instancetype)imageWithName:(NSString *)name
{

    // 這里調(diào)用imageWithName,相當(dāng)于調(diào)用imageName
    UIImage *image = [self imageWithName:name];

    if (image == nil) {
        NSLog(@"加載空的圖片");
    }
    return image;
}
@end
  • 交換原理
  • 交換之前


    交換之前
  • 交換之后


    交換之后

3.動態(tài)添加方法

  • 開發(fā)使用場景:如果一個類方法非常多讶迁,加載類到內(nèi)存的時候也非常耗費資源连茧,需要給每個方法生成映射表,可以動態(tài)給某個類巍糯,添加方法解決啸驯。
  • 經(jīng)典面試題:有沒有使用performSelector,主要考察的是有沒有使用動態(tài)添加過方法祟峦。
  • 簡單使用
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    Person *p = [[Person alloc] init];
    
    // 默認(rèn)person罚斗,沒有實現(xiàn)eat方法,可以通過performSelector調(diào)用宅楞,但是會報錯针姿。
    // 動態(tài)添加方法就不會報錯
    [p performSelector:@selector(eat)];
    
}


@end


@implementation Person
// void(*)()
// 默認(rèn)方法都有兩個隱式參數(shù)袱吆,
void eat(id self,SEL sel)
{
    NSLog(@"%@ %@",self,NSStringFromSelector(sel));
}

// 當(dāng)一個對象調(diào)用未實現(xiàn)的方法,會調(diào)用這個方法處理,并且會把對應(yīng)的方法列表傳過來.
// 剛好可以用來判斷搓幌,未實現(xiàn)的方法是不是我們想要動態(tài)添加的方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
    
    if (sel == @selector(eat)) {
        // 動態(tài)添加eat方法
        
        // 第一個參數(shù):給哪個類添加方法
        // 第二個參數(shù):添加方法的方法編號
        // 第三個參數(shù):添加方法的函數(shù)實現(xiàn)(函數(shù)地址)
        // 第四個參數(shù):函數(shù)的類型杆故,(返回值+參數(shù)類型) v:void @:對象->self :表示SEL->_cmd
        class_addMethod(self, @selector(eat), eat, "v@:");
        
    }
    
    return [super resolveInstanceMethod:sel];
}
@end

4.給分類添加屬性

  • 原理:給一個類聲明屬性,其實本質(zhì)就是給這個類添加關(guān)聯(lián)溉愁,并不是直接把這個值的內(nèi)存空間添加到類內(nèi)存空間处铛。
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // 給系統(tǒng)NSObject類動態(tài)添加屬性name

    NSObject *objc = [[NSObject alloc] init];
    objc.name = @"hjfrun";
    NSLog(@"%@",objc.name);
}
@end

// 定義關(guān)聯(lián)的key
static const char *key = "name";
@implementation NSObject (Property)

- (NSString *)name
{
    // 根據(jù)關(guān)聯(lián)的key,獲取關(guān)聯(lián)的值拐揭。
    return objc_getAssociatedObject(self, key);
}

- (void)setName:(NSString *)name
{
    // 第一個參數(shù):給哪個對象添加關(guān)聯(lián)
    // 第二個參數(shù):關(guān)聯(lián)的key撤蟆,通過這個key獲取
    // 第三個參數(shù):關(guān)聯(lián)的value
    // 第四個參數(shù):關(guān)聯(lián)的策略
    objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市堂污,隨后出現(xiàn)的幾起案子家肯,更是在濱河造成了極大的恐慌,老刑警劉巖盟猖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讨衣,死亡現(xiàn)場離奇詭異,居然都是意外死亡式镐,警方通過查閱死者的電腦和手機(jī)反镇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來娘汞,“玉大人歹茶,你說我怎么就攤上這事∧阆遥” “怎么了惊豺?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長禽作。 經(jīng)常有香客問我尸昧,道長,這世上最難降的妖魔是什么旷偿? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任彻磁,我火速辦了婚禮,結(jié)果婚禮上狸捅,老公的妹妹穿的比我還像新娘。我一直安慰自己累提,他們只是感情好尘喝,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著斋陪,像睡著了一般朽褪。 火紅的嫁衣襯著肌膚如雪置吓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天缔赠,我揣著相機(jī)與錄音衍锚,去河邊找鬼。 笑死嗤堰,一個胖子當(dāng)著我的面吹牛戴质,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播踢匣,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼告匠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了离唬?” 一聲冷哼從身側(cè)響起后专,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎输莺,沒想到半個月后戚哎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡嫂用,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年型凳,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尸折。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡啰脚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出实夹,到底是詐尸還是另有隱情橄浓,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布亮航,位于F島的核電站荸实,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏缴淋。R本人自食惡果不足惜准给,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望重抖。 院中可真熱鬧露氮,春花似錦、人聲如沸钟沛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽恨统。三九已至叁扫,卻和暖如春三妈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背莫绣。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工畴蒲, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人对室。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓模燥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親软驰。 傳聞我的和親對象是個殘疾皇子涧窒,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

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

  • 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的轉(zhuǎn)載 這篇文章完全是基于南峰子老師博客的...
    西木閱讀 30,544評論 33 466
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,682評論 0 9
  • OC是一門動態(tài)語言锭亏,它將很多靜態(tài)語言在編譯和鏈接時期做的事情推遲到了運行時來處理纠吴,這就意味著它不僅需要一個編譯器,...
    zziazm閱讀 205評論 0 0
  • 上圖:每一天慧瘤,我們都在進(jìn)步戴已。 上圖:金龍的花和花盆。 每一分一秒锅减,我們都離不開世間八法的侵襲糖儡。菩提心的教導(dǎo)甚為稀有...
    甘斯保健正果養(yǎng)生堂閱讀 418評論 0 0
  • 時間是從指縫間溜走的幸福,而我從指縫間看見我們愛情的模樣怔匣,溺水的愛情握联,只淹死了我。 01 我們吃飽喝足每瞒,坐在公園的...
    小理愛可樂閱讀 324評論 0 1