Objective-C之runtime學(xué)習(xí)筆記

一、寫在前面

Objective-C語言是動(dòng)態(tài)語言,在編譯階段并不決定調(diào)用那個(gè)函數(shù)物咳,只有在運(yùn)行的時(shí)候才去根據(jù)函數(shù)名調(diào)用對(duì)應(yīng)的函數(shù),稱為OC的動(dòng)態(tài)特性蹄皱。Objective-C一系列動(dòng)態(tài)特性的實(shí)現(xiàn)用的就是runtime览闰。
Objective-C方法調(diào)用實(shí)質(zhì)就是消息機(jī)制的轉(zhuǎn)發(fā),即讓對(duì)象發(fā)送消息夯接。
如:

People *p = [[People alloc] init];
[p eat];

調(diào)用eat方法的實(shí)質(zhì)就是:

objc_msgSend(p, @selector(eat));

其消息機(jī)制的轉(zhuǎn)發(fā)原理就是對(duì)象通過SEL去映射表中查找對(duì)應(yīng)的方法實(shí)現(xiàn)焕济。

二、動(dòng)態(tài)處理方法

1.替換方法

方法的替換指的是將原有的方法實(shí)現(xiàn)更改為自己制定的方法實(shí)現(xiàn)盔几,通過原有的方法名調(diào)用方法時(shí)執(zhí)行自己指定的方法晴弃。
我們更換下面兩個(gè)類的方法做一下替換:

@implementation People
- (void)eat
{
    NSLog(@"%s", __FUNCTION__);
}
@end

@implementation Dog
- (void)sleep
{
    NSLog(@"%s", __FUNCTION__);
}
@end

調(diào)用替換方法,將People的eat方法替換為Dog的sleep方法:

ReplaceMethod([People class], @selector(eat), [Dog class], @selector(sleep));

ReplaceMethod方法的實(shí)現(xiàn)如下:

void ReplaceMethod(Class originClass, SEL originSelector, Class targetClass, SEL targetSelector)
{
    Method targetMethod = class_getInstanceMethod(targetClass, targetSelector);
    class_replaceMethod(originClass, originSelector, method_getImplementation(targetMethod), method_getTypeEncoding(targetMethod));
}

調(diào)用People的eat方法看到的輸出為Dog的sleep方法的打友放摹:

People *p = [[People alloc] init];
[p eat];
2.交換方法

方法交換是指交換兩個(gè)方法的實(shí)現(xiàn)上鞠,如有甲、乙兩個(gè)方法芯丧,調(diào)用甲方法實(shí)際上調(diào)用的是乙方法的實(shí)現(xiàn)芍阎,調(diào)用乙方法實(shí)際上調(diào)用的是甲方法的實(shí)現(xiàn)。
還是People類和Dog類缨恒,交換兩個(gè)類的方法:

ExchangeInstanceMethod([People class], @selector(eat), [Dog class], @selector(sleep));

ExchangeInstanceMethod方法的實(shí)現(xiàn):

void ExchangeInstanceMethod(Class firstClass, SEL firstSelector, Class secondClass, SEL secondSelector)
{
    Method firstMethod = class_getInstanceMethod(firstClass, firstSelector);
    Method secondMethod = class_getInstanceMethod(secondClass, secondSelector);
    method_exchangeImplementations(firstMethod, secondMethod);
}

調(diào)用People的eat方法:

People *p = [[People alloc] init];
[p eat];

打印效果可以看到調(diào)用的是Dog的sleep方法:


調(diào)用Dog的sleep方法:

Dog *d = [[Dog alloc] init];
[d sleep];

打印效果可以看出調(diào)用的是People的eat方法:

3.添加方法:

類可以通過performSelector直接調(diào)用類的方法谴咸,如:

People *p = [[People alloc] init];
[p eat];

可以這樣調(diào)用:

People *p = [[People alloc] init];
[p performSelector:@selector(eat)];

class_addMethod為類添加一個(gè)未曾實(shí)現(xiàn)的方法,可以通過performSelector進(jìn)行調(diào)用骗露。
如將Dog的sleep方法添加到People類上:

AddMethod([People class], @selector(sleep), [Dog class], @selector(sleep));

AddMethod方法的具體實(shí)現(xiàn):

void AddMethod(Class cls, SEL mSelector, Class lCls, SEL lSelector)
{
    Method lMethod = class_getInstanceMethod(lCls, lSelector);
    class_addMethod(cls, mSelector, method_getImplementation(lMethod), method_getTypeEncoding(lMethod));
}

通過performSelector調(diào)用People的sleep的方法岭佳,打印結(jié)果為Dog的sleep方法:

People *p = [[People alloc] init];
[p performSelector:@selector(sleep)];

三、獲取類的屬性和成員變量

1.獲取類的屬性

定義一個(gè)唱片的類MusicAlbum:

@interface MusicAlbum : NSObject

@property (nonatomic, strong) NSString *albumName;

@property (nonatomic, strong) NSString *author;

@property (nonatomic, strong) NSArray *musicList;

@property (nonatomic, assign) int64_t publishTime;

@end

通過class_copyPropertyList獲取類的屬性列表萧锉,再通過property_getName和property_getAttributes獲取屬性的名字和類型信息珊随。

unsigned int count = 0;
objc_property_t *propertys = class_copyPropertyList([MusicAlbum class], &count);
for (int i = 0; i < count; i++) {
    objc_property_t property = propertys[i];
    NSString *propertyName = [NSString stringWithUTF8String:property_getName(property)];
    NSString *attriableName = [NSString stringWithUTF8String:property_getAttributes(property)];
    NSLog(@"property name is: %@, -----> attriable is: %@", propertyName, attriableName);
}


輸出的屬性名對(duì)應(yīng)相應(yīng)的屬性類型,其中q代表的是長(zhǎng)整型。
Objective-C中基本數(shù)據(jù)類型包括短整型(short)叶洞、整形(int)鲫凶、長(zhǎng)整型(long)、浮點(diǎn)型(float)衩辟、雙精度浮點(diǎn)型(double)螟炫、字符型(char)、布爾型(BOOL)惭婿,對(duì)應(yīng)的標(biāo)識(shí)分別為:short(s)不恭、int(i)、long(q)财饥、float(f)换吧、double(d)、char(c)钥星、BOOL(B)沾瓦;引用數(shù)據(jù)類型以對(duì)應(yīng)的屬性類型顯示出來,如:musicList是數(shù)組類型谦炒,而數(shù)組又是引用類型贯莺,因此在屬性類型信息上可以看到T@"NSArray",&,N,V_musicList的信息。

2.獲取類的成員變量

對(duì)MusicAlbum類添加一些變量:

@private
int _age;
double _height;

@public
NSString *_nextMusicName;

通過class_copyIvarList獲取類的成員變量列表宁改,通過ivar_getName和ivar_getTypeEncoding獲取成員變量名和成員變量類型信息缕探。

unsigned int count = 0;
Ivar *ivars = class_copyIvarList([MusicAlbum class], &count);
for (int i = 0; i < count; i++) {
    Ivar ivar = ivars[i];
    NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
    NSString *ivarType = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
    NSLog(@"ivar name is: %@,-----> type is: %@", ivarName, ivarType);
}

在打印信息中可以看到通過Ivar獲取類的成員變量包括類的屬性、private變量和public變量还蹲。
成員變量類型信息和屬性類型信息是相同的爹耗,分為基本數(shù)據(jù)類型和引用數(shù)據(jù)類型,基本數(shù)據(jù)類型有相對(duì)應(yīng)的標(biāo)識(shí)谜喊,引用數(shù)據(jù)類型以其對(duì)應(yīng)的類型名標(biāo)識(shí)出來潭兽。

四、關(guān)聯(lián)對(duì)象

可以通過objc_setAssociatedObject和objc_getAssociatedObject給類添加屬性斗遏。
如通過分類給UIColor添加一個(gè)金色顏色屬性:

@interface UIColor (color)
@property (class, nonatomic, readonly) UIColor *goldColor;
@end

由于金色屬性是類屬性山卦,并且是一個(gè)只讀屬性,通過getter方法添加這個(gè)屬性诵次。

static NSString const *gold_color_key = @"gold_color_key";
@implementation UIColor (color)

+ (UIColor *)goldColor {
    UIColor *color = objc_getAssociatedObject(self, &gold_color_key);
    if (!color) {
        color = [UIColor colorWithRed:1 green:1 blue:0 alpha:1.0];
        objc_setAssociatedObject(self, &gold_color_key, color, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    return color;
}

@end

Demo
參考文章:
消息處理之performSelector
OC關(guān)聯(lián)對(duì)象小結(jié)(一)
剖析runtime,看完包懂
Objective-C 中的消息與消息轉(zhuǎn)發(fā)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末账蓉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子逾一,更是在濱河造成了極大的恐慌剔猿,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,042評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嬉荆,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡酷含,警方通過查閱死者的電腦和手機(jī)鄙早,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,996評(píng)論 2 384
  • 文/潘曉璐 我一進(jìn)店門汪茧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人限番,你說我怎么就攤上這事舱污。” “怎么了弥虐?”我有些...
    開封第一講書人閱讀 156,674評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵扩灯,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我霜瘪,道長(zhǎng)珠插,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,340評(píng)論 1 283
  • 正文 為了忘掉前任颖对,我火速辦了婚禮捻撑,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘缤底。我一直安慰自己顾患,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
  • 文/花漫 我一把揭開白布个唧。 她就那樣靜靜地躺著江解,像睡著了一般。 火紅的嫁衣襯著肌膚如雪徙歼。 梳的紋絲不亂的頭發(fā)上犁河,一...
    開封第一講書人閱讀 49,749評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音鲁沥,去河邊找鬼呼股。 笑死,一個(gè)胖子當(dāng)著我的面吹牛画恰,可吹牛的內(nèi)容都是我干的彭谁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,902評(píng)論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼允扇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼缠局!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起考润,我...
    開封第一講書人閱讀 37,662評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤狭园,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后糊治,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體唱矛,經(jīng)...
    沈念sama閱讀 44,110評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了绎谦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片管闷。...
    茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖窃肠,靈堂內(nèi)的尸體忽然破棺而出包个,到底是詐尸還是另有隱情,我是刑警寧澤冤留,帶...
    沈念sama閱讀 34,258評(píng)論 4 328
  • 正文 年R本政府宣布碧囊,位于F島的核電站,受9級(jí)特大地震影響纤怒,放射性物質(zhì)發(fā)生泄漏糯而。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
  • 文/蒙蒙 一肪跋、第九天 我趴在偏房一處隱蔽的房頂上張望歧蒋。 院中可真熱鬧,春花似錦州既、人聲如沸谜洽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,726評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阐虚。三九已至,卻和暖如春蚌卤,著一層夾襖步出監(jiān)牢的瞬間实束,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,952評(píng)論 1 264
  • 我被黑心中介騙來泰國(guó)打工逊彭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留咸灿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,271評(píng)論 2 360
  • 正文 我出身青樓侮叮,卻偏偏與公主長(zhǎng)得像避矢,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子囊榜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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

  • 面向?qū)ο笾饕槍?duì)面向過程审胸。 面向過程的基本單元是函數(shù)。 什么是對(duì)象:EVERYTHING IS OBJECT(萬物...
    sinpi閱讀 1,046評(píng)論 0 4
  • Objective-C 1. import的用法 拷貝文件內(nèi)容可以自動(dòng)防止文件的內(nèi)容被重復(fù)拷貝(#define宏定...
    馬文濤閱讀 5,333評(píng)論 3 17
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法卸勺,類相關(guān)的語法砂沛,內(nèi)部類的語法,繼承相關(guān)的語法曙求,異常的語法碍庵,線程的語...
    子非魚_t_閱讀 31,598評(píng)論 18 399
  • 1.import static是Java 5增加的功能,就是將Import類中的靜態(tài)方法映企,可以作為本類的靜態(tài)方法來...
    XLsn0w閱讀 1,214評(píng)論 0 2
  • 一條鐵路 悠悠長(zhǎng)長(zhǎng)地臥在林間 沒有列車駛過…… 它平靜地像是一排低矮的灌木 任憑著青苔與銹跡生長(zhǎng) 我不過是過客,想...
    郁衡子閱讀 235評(píng)論 0 0