17 runtime-之API詳解+使用

序言

本篇文章主要介紹runtime有關(guān)API及使用

一 類

1.1 動(dòng)態(tài)創(chuàng)建一個(gè)類(參數(shù):父類渣慕,類名,額外的內(nèi)存空間)

Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes)

1.2 注冊(cè)一個(gè)類(要在類注冊(cè)之前添加成員變量)

void objc_registerClassPair(Class cls)

1.3 銷毀一個(gè)類

void objc_disposeClassPair(Class cls)

  • 以上三個(gè)方法使用下面例子做講解
// 建一個(gè)命令行工程
#import <Foundation/Foundation.h>
#import <objc/runtime.h>

void run(id self, SEL _cmd) {
    NSLog(@"_____ %@ - %@", self, NSStringFromSelector(_cmd));
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        // 動(dòng)態(tài)創(chuàng)建一個(gè)類
        Class newClass = objc_allocateClassPair([NSObject class], "CSDog", 0);
        // 添加屬性
        class_addIvar(newClass, "_age", 4, 1, @encode(int));
        class_addIvar(newClass, "_weight", 4, 1, @encode(int));
        // 添加方法
        class_addMethod(newClass, @selector(run), (IMP)run, "v@:");
        // 注冊(cè)類
        objc_registerClassPair(newClass);

        id dog = [[newClass alloc] init];
        [dog setValue:@10 forKey:@"_age"];
        [dog setValue:@20 forKey:@"_weight"];
        [dog run];

        NSLog(@"%@ %@", [dog valueForKey:@"_age"], [dog valueForKey:@"_weight"]);

        // 在不需要這個(gè)類時(shí)釋放
        objc_disposeClassPair(newClass);
    }
    return 0;
}

運(yùn)行結(jié)果

1653926-b40ac7664f8818a8.png
1.4 獲取isa指向的Class

Class object_getClass(id obj)

1.5 設(shè)置isa指向的Class

Class object_setClass(id obj, Class cls)

1.6 判斷一個(gè)OC對(duì)象是否為Class

BOOL object_isClass(id obj)

  • 上面三個(gè)方法以下面代碼做例子
@interface CSPersion : NSObject
- (void)run;
@end

@implementation CSPersion
- (void)run {
    NSLog(@"%s", __func__);
}
@end

@interface CSCar : NSObject
- (void)run;
@end

@implementation CSCar
- (void)run {
    NSLog(@"%s", __func__);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        CSPersion *persion = [[CSPersion alloc] init];
        [persion run];

        object_setClass(persion, [CSCar class]);
        [persion run];

        object_getClass([CSPersion class]);

        NSLog(@"%p %p", object_getClass([CSPersion class]), [CSPersion class]);

        NSLog(@"%d %d %d",
              object_isClass(persion),
              object_isClass([CSPersion class]),
              object_isClass(object_getClass([CSPersion class]))
              );
    }
    return 0;
}

運(yùn)行結(jié)果如下

1653926-651756750eed1cc0.png
1.7 判斷一個(gè)Class是否為元類

BOOL class_isMetaClass(Class cls)

1.8 獲取父類

Class class_getSuperclass(Class cls)

二 成員變量

公共使用類

@interface CSPersion : NSObject
@property (assign, nonatomic) int ID;
@property (assign, nonatomic) int weight;
@property (assign, nonatomic) int age;
@property (copy, nonatomic) NSString *name;
- (void)run;
@end

2.1 獲取一個(gè)實(shí)例變量信息
  • Ivar class_getInstanceVariable(Class cls, const char *name)
2.2 獲取成員變量的相關(guān)信息
  • const char *ivar_getName(Ivar v)
  • const char *ivar_getTypeEncoding(Ivar v)

2.1,2.2使用如下代碼做例子

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        // 1.獲取成員變量信息
        Ivar ageIvar = class_getInstanceVariable([CSPersion class], "_age");
        NSLog(@"%s %s",ivar_getName(ageIvar),ivar_getTypeEncoding(ageIvar));
    }
    return 0;
}

運(yùn)行結(jié)果

1653926-76f34c1b7270d0c4.png
2.3 設(shè)置和獲取成員變量的值
  • void object_setIvar(id obj, Ivar ivar, id value)
  • id object_getIvar(id obj, Ivar ivar)

代碼例子如下

int main(int argc, const char * argv[]) {
    @autoreleasepool { 
        // 2\. 設(shè)置和獲取成員變量的值
        CSPersion *persion = [[CSPersion alloc] init];
        Ivar nameIvar = class_getInstanceVariable([CSPersion class], "_name");
        Ivar ageIvar = class_getInstanceVariable([CSPersion class], "_age");

        object_setIvar(persion, nameIvar, @"123");
        object_setIvar(persion, ageIvar, (__bridge id)(void *)10);
        NSLog(@"%@ %d", persion.name, persion.age);
    }
    return 0;
}

運(yùn)行結(jié)果如下

1653926-ac4db8ed261e1ddc.png
2.4 動(dòng)態(tài)添加成員變量(已經(jīng)注冊(cè)的類是不能動(dòng)態(tài)添加成員變量的)
  • BOOL class_addIvar(Class cls, const char * name, size_t size, uint8_t alignment, const char * types)
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 動(dòng)態(tài)創(chuàng)建一個(gè)類
        Class newClass = objc_allocateClassPair([NSObject class], "CSDog", 0);
        // 添加屬性
        class_addIvar(newClass, "_age", 4, 1, @encode(int));
        class_addIvar(newClass, "_weight", 4, 1, @encode(int));
        // 添加方法
        class_addMethod(newClass, @selector(run), (IMP)run, "v@:");
        // 注冊(cè)類
        objc_registerClassPair(newClass);

        id dog = [[newClass alloc] init];
        [dog setValue:@10 forKey:@"_age"];
        [dog setValue:@20 forKey:@"_weight"];
        [dog run];

        NSLog(@"%@ %@", [dog valueForKey:@"_age"], [dog valueForKey:@"_weight"]);

        // 在不需要這個(gè)類時(shí)釋放
        objc_disposeClassPair(newClass);
    }
    return 0;
}

運(yùn)行結(jié)果如下

1653926-5ac8ad7308f2cc31.png
2.5 拷貝實(shí)例變量列表(最后需要調(diào)用free釋放)
  • Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 4.成員變量的數(shù)量
        unsigned int count;
        Ivar *ivars = class_copyIvarList([CSPersion class], &count);
        for (int i = 0; i < count; i++) {
            // 取出i位置的成員變量
            Ivar ivar = ivars[I];
            NSLog(@"%s %s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
        }
        free(ivars);
    }
    return 0;
}

運(yùn)行結(jié)果如下

1653926-81956569ae59709b.png
三 屬性
3.1 獲取一個(gè)屬性
  • objc_property_t class_getProperty(Class cls, const char *name)
3.2 拷貝屬性列表(最后需要調(diào)用free釋放)
  • objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
3.3 動(dòng)態(tài)添加屬性
  • BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
3.4 動(dòng)態(tài)替換屬性
  • void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
3.5 獲取屬性的一些信息
  • const char *property_getName(objc_property_t property)
  • const char *property_getAttributes(objc_property_t property)
四 方法
4.1 獲得一個(gè)實(shí)例方法鸡岗、類方法
  • Method class_getInstanceMethod(Class cls, SEL name)
  • Method class_getClassMethod(Class cls, SEL name)
4.2 方法實(shí)現(xiàn)相關(guān)操作
  • IMP class_getMethodImplementation(Class cls, SEL name)
  • IMP method_setImplementation(Method m, IMP imp)
  • void method_exchangeImplementations(Method m1, Method m2)
4.3 拷貝方法列表(最后需要調(diào)用free釋放)
  • Method *class_copyMethodList(Class cls, unsigned int *outCount)
4.4 動(dòng)態(tài)添加方法
  • BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
4.5 動(dòng)態(tài)替換方法
  • IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
4.6 獲取方法的相關(guān)信息(帶有copy的需要調(diào)用free去釋放)
  • SEL method_getName(Method m)
  • IMP method_getImplementation(Method m)
  • const char *method_getTypeEncoding(Method m)
  • unsigned int method_getNumberOfArguments(Method m)
  • char *method_copyReturnType(Method m)
  • char *method_copyArgumentType(Method m, unsigned int index)
4.7 選擇器相關(guān)
  • const char *sel_getName(SEL sel)
  • SEL sel_registerName(const char *str)
4.8 用block作為方法實(shí)現(xiàn)
  • IMP imp_implementationWithBlock(id block)
  • id imp_getBlock(IMP anImp)
  • BOOL imp_removeBlock(IMP anImp)

本文參考:
路飛_Luck (http://www.reibang.com/p/07f7b96bb03f)
以及借鑒MJ的教程視頻
非常感謝.


項(xiàng)目連接地址-runtime_API
項(xiàng)目連接地址-runtime_exchangeMethod

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市殷绍,隨后出現(xiàn)的幾起案子洛搀,更是在濱河造成了極大的恐慌,老刑警劉巖译打,帶你破解...
    沈念sama閱讀 206,378評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異拇颅,居然都是意外死亡奏司,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門樟插,熙熙樓的掌柜王于貴愁眉苦臉地迎上來韵洋,“玉大人竿刁,你說我怎么就攤上這事√掠В” “怎么了食拜?”我有些...
    開封第一講書人閱讀 152,702評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長副编。 經(jīng)常有香客問我负甸,道長,這世上最難降的妖魔是什么痹届? 我笑而不...
    開封第一講書人閱讀 55,259評(píng)論 1 279
  • 正文 為了忘掉前任呻待,我火速辦了婚禮,結(jié)果婚禮上队腐,老公的妹妹穿的比我還像新娘蚕捉。我一直安慰自己,他們只是感情好柴淘,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,263評(píng)論 5 371
  • 文/花漫 我一把揭開白布迫淹。 她就那樣靜靜地躺著,像睡著了一般为严。 火紅的嫁衣襯著肌膚如雪敛熬。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評(píng)論 1 285
  • 那天梗脾,我揣著相機(jī)與錄音荸型,去河邊找鬼。 笑死炸茧,一個(gè)胖子當(dāng)著我的面吹牛瑞妇,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梭冠,決...
    沈念sama閱讀 38,349評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼辕狰,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了控漠?” 一聲冷哼從身側(cè)響起蔓倍,我...
    開封第一講書人閱讀 36,979評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎盐捷,沒想到半個(gè)月后偶翅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡碉渡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,938評(píng)論 2 323
  • 正文 我和宋清朗相戀三年聚谁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滞诺。...
    茶點(diǎn)故事閱讀 38,059評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡形导,死狀恐怖环疼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情朵耕,我是刑警寧澤炫隶,帶...
    沈念sama閱讀 33,703評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站阎曹,受9級(jí)特大地震影響伪阶,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜芬膝,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,257評(píng)論 3 307
  • 文/蒙蒙 一望门、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧锰霜,春花似錦筹误、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至友存,卻和暖如春祷膳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背屡立。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評(píng)論 1 262
  • 我被黑心中介騙來泰國打工直晨, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膨俐。 一個(gè)月前我還...
    沈念sama閱讀 45,501評(píng)論 2 354
  • 正文 我出身青樓勇皇,卻偏偏與公主長得像,于是被迫代替她去往敵國和親焚刺。 傳聞我的和親對(duì)象是個(gè)殘疾皇子敛摘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,792評(píng)論 2 345

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

  • 人生就要不斷挑戰(zhàn)自己 迎風(fēng)傲雪
    杏林月閱讀 174評(píng)論 0 2
  • 一整個(gè)冬天我都在等待什么,一場(chǎng)雨乳愉,一陣風(fēng)兄淫,開花的樹,或者是其它什么蔓姚。 中秋節(jié)快到的時(shí)候捕虽,我送父親去腫瘤...
    木葉田閱讀 197評(píng)論 1 0
  • 今天和朋友一起去了一趟經(jīng)偵大隊(duì)登記,最開始一直是有一些忐忑的坡脐。因?yàn)樽约旱囊恍┦д`泄私,做了一些錯(cuò)誤的投資決定,直接導(dǎo)致...
    飛揚(yáng)讀書閱讀 226評(píng)論 0 0
  • 雪后 雪落公園滿地詩。 枯荷寂寞立陂池挖滤。 可憐檐角無家雀, 今夜不知宿那枝浅役?
    上善若水容閱讀 63評(píng)論 0 1