objective-c runtime practice

1. 獲取properties和實例變量

栗子代碼:

-------------------------Person.h
@interface Person : NSObject 
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSString *sex;
- (void)printClass;
- (void)doingHomework;
@end
-------------------------Person.m
@implementation Person{
    NSString *_class;
    NSString *_age;
}
@dynamic name;
-------------------------main.m

unsigned int outCount, i;
id PersonClass=objc_getClass("Person");

objc_property_t *properties=class_copyPropertyList(PersonClass, &outCount);
for (i=0; i<outCount; i++) {
    objc_property_t property=properties[i];
    fprintf(stdout, "Properties: %s\n",property_getName(property));
    
}

Ivar *ivar=class_copyIvarList(PersonClass, &outCount);
for (i=0; i<outCount; i++) {
    Ivar var=ivar[i];
    fprintf(stdout, "Ivars: %s\n",ivar_getName(var));
}

輸出

Properties: name
Properties: sex
Ivar: _class
Ivar: _age
Ivar: _sex

我們定義了2個properties:namesex
2個變量:_class场躯、_age

但注意到我們的class_copyIvarList僅獲取到了3個變量并打印出來了,沒有_name推盛,這是由于我們@dynamic修飾了這個property,系統(tǒng)不會為@dynamic修飾的property生成變量谦铃。

2. Objective-C Associated Objects

runtime系統(tǒng)讓objc支持向?qū)嵗?instance)動態(tài)添加對象(object)。

void objc_setAssociatedObject ( id object, const void *key, id value, objc_AssociationPolicy policy );
id objc_getAssociatedObject ( id object, const void *key );
void objc_removeAssociatedObjects ( id object );

那這個功能有什么用呢?最先想到的就是:Category
我們知道category中可以添加方法,但是不能添加實例變量(instance variables)师妙,雖然我們可以在interface文件中使用@property申明一個property,語法上沒有問題怔檩,但編譯器不會幫你synthesize任何實例變量,也不會幫你實現(xiàn)getter和setter方法(僅有申明)薛训。
我們可以手動添加getter和setter仑氛,但是卻沒辦法增加一個實例變量來存儲和跟蹤數(shù)據(jù)變化锯岖。

Associated Objects登場介袜,上代碼:

-------------------------Person+JobTitle.h
#import "Person.h"
@interface Person (JobTitle)
@property (strong, nonatomic) NSString *jobTitle;
@end
-------------------------Person+JobTitle.m
#import "Person+JobTitle.h"
#import <objc/runtime.h>

static NSString * const KEY=@"associateObjectKey";

@implementation Person (JobTitle)

- (NSString *)jobTitle {
    return objc_getAssociatedObject(self, &KEY);
}

- (void)setJobTitle:(NSString *)jobTitle {
    if ([jobTitle isEqualToString:objc_getAssociatedObject(self, &KEY)]) {
        return;
    } else {
        objc_setAssociatedObject(self, &KEY, jobTitle, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}
@end
-------------------------main.m
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *a=[Person new];
        a.jobTitle=@"Programmer: I love Objective-C";
        NSLog(@"jobTitle: %@",[a jobTitle]);
...
}

輸出結(jié)果

jobTitle: Programmer: I love Objective-C

完美的擴展了實例的屬性,而且不用子類化它趋箩,通過runtime非常靈活的實現(xiàn)了這個功能叫确。

3. Method Swizzling

通過Method Swizzling我們可以在運行時替換某個Selector的IMP,我們通過下面代碼演示一下:

----------------------Person.m
@implementation Person{
    NSString *_class;
    NSString *_age;
}

@dynamic name;

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        SEL originSel=@selector(printClass);
        SEL swizzlingSel=@selector(swizzlingPrint);

        Method originMethod=class_getInstanceMethod(self, originSel);
        Method swizzlingMethod=class_getInstanceMethod(self, swizzlingSel);
        
        method_exchangeImplementations(originMethod, swizzlingMethod);
    });
}

- (void)printClass {
    NSLog(@"[SEL:%@]----but I am printClass",NSStringFromSelector(_cmd));
}

- (void)swizzlingPrint {
    NSLog(@"[SEL:%@]-----but I am swizzlingPrint",NSStringFromSelector(_cmd));
}
----------------------main.m
Person *a=[Person new];
[a printClass];
[a swizzlingPrint];

執(zhí)行結(jié)果

[SEL:printClass]-----but I am swizzlingPrint
[SEL:swizzlingPrint]----but I am printClass

可以看到selector還是原來的selector飞盆,但是執(zhí)行的內(nèi)容變了吓歇。很神奇票腰,這就是runtime消息的魅力杏慰,非常靈活测柠。
我們可以通過這個特性轰胁,在某些時候替換掉系統(tǒng)的方法實例為自己的。

補充說明:

  • method swizzling最好是放在+(void)load方法中赃阀,這個方法從NSObject中繼承,這個方法僅會在類或者category在加入runtime時調(diào)用一次观游。即便如此最好也加上dispatch_once肖抱,如果method_exchangeImplementations被調(diào)用兩次就又重新被換回來了,沒效果,這個很好理解吧吮蛹。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末潮针,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子每篷,更是在濱河造成了極大的恐慌焦读,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件仑嗅,死亡現(xiàn)場離奇詭異张症,居然都是意外死亡俗他,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門地沮,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人周伦,你說我怎么就攤上這事∽ㄅ玻” “怎么了片排?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵率寡,是天一觀的道長迫卢。 經(jīng)常有香客問我乾蛤,道長捅僵,這世上最難降的妖魔是什么庙楚? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮酪捡,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘逛薇。我一直安慰自己塞祈,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布尤蛮。 她就那樣靜靜地躺著斯议,像睡著了一般哼御。 火紅的嫁衣襯著肌膚如雪焊唬。 梳的紋絲不亂的頭發(fā)上看靠,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音鸥滨,去河邊找鬼谤祖。 笑死,一個胖子當著我的面吹牛粥喜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播额湘,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锋华,長吁一口氣:“原來是場噩夢啊……” “哼供置!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绽快,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤坊罢,失蹤者是張志新(化名)和其女友劉穎活孩,沒想到半個月后物遇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體憾儒,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡起趾,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年训裆,在試婚紗的時候發(fā)現(xiàn)自己被綠了眶根。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片属百。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡族扰,死狀恐怖厌丑,靈堂內(nèi)的尸體忽然破棺而出蹄衷,到底是詐尸還是另有隱情,我是刑警寧澤愧口,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布类茂,位于F島的核電站,受9級特大地震影響巩检,放射性物質(zhì)發(fā)生泄漏兢哭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一冲秽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锉桑,春花似錦窍株、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至祈搜,卻和暖如春较店,著一層夾襖步出監(jiān)牢的瞬間梁呈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工官卡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留醋虏,地道東北人。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓毛秘,卻偏偏與公主長得像,于是被迫代替她去往敵國和親叫挟。 傳聞我的和親對象是個殘疾皇子限煞,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

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

  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 731評論 0 2
  • 本文詳細整理了 Cocoa 的 Runtime 系統(tǒng)的知識署驻,它使得 Objective-C 如虎添翼旺上,具備了靈活的...
    lylaut閱讀 800評論 0 4
  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,709評論 0 9
  • 本文轉(zhuǎn)載自:http://yulingtianxia.com/blog/2014/11/05/objective-...
    ant_flex閱讀 758評論 0 1
  • 文中的實驗代碼我放在了這個項目中。 以下內(nèi)容是我通過整理[這篇博客] (http://yulingtianxia....
    茗涙閱讀 923評論 0 6