Runtime使用

類與對(duì)象操作函數(shù)

runtime有很多的函數(shù)可以操作類和對(duì)象缩抡。類相關(guān)的是class為前綴众雷,對(duì)象相關(guān)操作是objc或object_為前綴讨越。

類相關(guān)操作函數(shù)

name:

// 獲取類的類名
const char * class_getName ( Class cls ); 

super_class和meta-class:

// 獲取類的父類
Class class_getSuperclass ( Class cls );

// 判斷給定的Class是否是一個(gè)meta class
BOOL class_isMetaClass ( Class cls );

instance_size:

// 獲取實(shí)例大小
size_t class_getInstanceSize ( Class cls );

成員變量(ivars)及屬性:

//成員變量操作函數(shù)
// 獲取類中指定名稱實(shí)例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );

// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );

// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); //這個(gè)只能夠向在runtime時(shí)創(chuàng)建的類添加成員變量

// 獲取整個(gè)成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount ); //必須使用free()來(lái)釋放這個(gè)數(shù)組

//屬性操作函數(shù)
// 獲取類中指定名稱實(shí)例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );

// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );

// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );

// 獲取整個(gè)成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );

methodLists:

// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); //和成員變量不同的是可以為類動(dòng)態(tài)添加方法远搪。如果有同名會(huì)返回NO峡捡,修改的話需要使用method_setImplementation

// 獲取實(shí)例方法
Method class_getInstanceMethod ( Class cls, SEL name );

// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );

// 獲取所有方法的數(shù)組
Method * class_copyMethodList ( Class cls, unsigned int *outCount );

// 替代方法的實(shí)現(xiàn)
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );

// 返回方法的具體實(shí)現(xiàn)
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );

// 類實(shí)例是否響應(yīng)指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );

objc_protocol_list:

// 添加協(xié)議
BOOL class_addProtocol ( Class cls, Protocol *protocol );

// 返回類是否實(shí)現(xiàn)指定的協(xié)議
BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );

// 返回類實(shí)現(xiàn)的協(xié)議列表
Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );

version:

// 獲取版本號(hào)
int class_getVersion ( Class cls );

// 設(shè)置版本號(hào)
void class_setVersion ( Class cls, int version );
類和函數(shù)的使用例子

通過(guò)實(shí)例來(lái)消化下上面的那些函數(shù):

//-----------------------------------------------------------
// MyClass.h
@interface MyClass : NSObject <NSCopying, NSCoding>
@property (nonatomic, strong) NSArray *array;
@property (nonatomic, copy) NSString *string;
- (void)method1;
- (void)method2;
+ (void)classMethod1;
@end

//-----------------------------------------------------------
// MyClass.m
#import "MyClass.h"
@interface MyClass () {
NSInteger _instance1;
NSString * _instance2;
}
@property (nonatomic, assign) NSUInteger integer;
- (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2;
@end

@implementation MyClass
+ (void)classMethod1 {
}

- (void)method1 {
     NSLog(@"call method method1");
}

- (void)method2 {
}

- (void)method3WithArg1:(NSInteger)arg1 arg2:(NSString *)arg2 {
     NSLog(@"arg1 : %ld, arg2 : %@", arg1, arg2);
}

@end

//-----------------------------------------------------------
// main.h

#import "MyClass.h"
#import "MySubClass.h"
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
     @autoreleasepool {
          MyClass *myClass = [[MyClass alloc] init];
          unsigned int outCount = 0;
          Class cls = myClass.class;
          // 類名
          NSLog(@"class name: %s", class_getName(cls));    
          NSLog(@"==========================================================");

          // 父類
          NSLog(@"super class name: %s", class_getName(class_getSuperclass(cls)));
          NSLog(@"==========================================================");

          // 是否是元類
          NSLog(@"MyClass is %@ a meta-class", (class_isMetaClass(cls) ? @"" : @"not"));
          NSLog(@"==========================================================");

          Class meta_class = objc_getMetaClass(class_getName(cls));
          NSLog(@"%s's meta-class is %s", class_getName(cls), class_getName(meta_class));
          NSLog(@"==========================================================");

          // 變量實(shí)例大小
          NSLog(@"instance size: %zu", class_getInstanceSize(cls));
          NSLog(@"==========================================================");

          // 成員變量
          Ivar *ivars = class_copyIvarList(cls, &outCount);
          for (int i = 0; i < outCount; i++) {
               Ivar ivar = ivars[i];
               NSLog(@"instance variable's name: %s at index: %d", ivar_getName(ivar), i);
          }

          free(ivars);

          Ivar string = class_getInstanceVariable(cls, "_string");
          if (string != NULL) {
               NSLog(@"instace variable %s", ivar_getName(string));
          }

          NSLog(@"==========================================================");

          // 屬性操作
          objc_property_t * properties = class_copyPropertyList(cls, &outCount);
          for (int i = 0; i < outCount; i++) {
               objc_property_t property = properties[i];
               NSLog(@"property's name: %s", property_getName(property));
          }

          free(properties);

          objc_property_t array = class_getProperty(cls, "array");
          if (array != NULL) {
               NSLog(@"property %s", property_getName(array));
          }

          NSLog(@"==========================================================");

          // 方法操作
          Method *methods = class_copyMethodList(cls, &outCount);
          for (int i = 0; i < outCount; i++) {
               Method method = methods[i];
               NSLog(@"method's signature: %s", method_getName(method));
          }

          free(methods);

          Method method1 = class_getInstanceMethod(cls, @selector(method1));
          if (method1 != NULL) {
               NSLog(@"method %s", method_getName(method1));
          }

          Method classMethod = class_getClassMethod(cls, @selector(classMethod1));
          if (classMethod != NULL) {
               NSLog(@"class method : %s", method_getName(classMethod));
          }

          NSLog(@"MyClass is%@ responsd to selector: method3WithArg1:arg2:", class_respondsToSelector(cls, @selector(method3WithArg1:arg2:)) ? @"" : @" not");

          IMP imp = class_getMethodImplementation(cls, @selector(method1));
          imp();

          NSLog(@"==========================================================");

          // 協(xié)議
          Protocol * __unsafe_unretained * protocols = class_copyProtocolList(cls, &outCount);
          Protocol * protocol;
          for (int i = 0; i < outCount; i++) {
               protocol = protocols[i];
               NSLog(@"protocol name: %s", protocol_getName(protocol));
          }

          NSLog(@"MyClass is%@ responsed to protocol %s", class_conformsToProtocol(cls, protocol) ? @"" : @" not", protocol_getName(protocol));

          NSLog(@"==========================================================");
     }
     return 0;
}

輸出結(jié)果:

2014-10-22 19:41:37.452 RuntimeTest[3189:156810] class name: MyClass
2014-10-22 19:41:37.453 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.454 RuntimeTest[3189:156810] super class name: NSObject
2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass is not a meta-class
2014-10-22 19:41:37.454 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.454 RuntimeTest[3189:156810] MyClass's meta-class is MyClass
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance size: 48
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance1 at index: 0
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _instance2 at index: 1
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _array at index: 2
2014-10-22 19:41:37.455 RuntimeTest[3189:156810] instance variable's name: _string at index: 3
2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instance variable's name: _integer at index: 4
2014-10-22 19:41:37.463 RuntimeTest[3189:156810] instace variable _string
2014-10-22 19:41:37.463 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: array
2014-10-22 19:41:37.463 RuntimeTest[3189:156810] property's name: string
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property's name: integer
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] property array
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method1
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method2
2014-10-22 19:41:37.464 RuntimeTest[3189:156810] method's signature: method3WithArg1:arg2:
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: integer
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setInteger:
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: array
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: string
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setString:
2014-10-22 19:41:37.465 RuntimeTest[3189:156810] method's signature: setArray:
2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method's signature: .cxx_destruct
2014-10-22 19:41:37.466 RuntimeTest[3189:156810] method method1
2014-10-22 19:41:37.466 RuntimeTest[3189:156810] class method : classMethod1
2014-10-22 19:41:37.466 RuntimeTest[3189:156810] MyClass is responsd to selector: method3WithArg1:arg2:
2014-10-22 19:41:37.467 RuntimeTest[3189:156810] call method method1
2014-10-22 19:41:37.467 RuntimeTest[3189:156810] ==========================================================
2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCopying
2014-10-22 19:41:37.467 RuntimeTest[3189:156810] protocol name: NSCoding
2014-10-22 19:41:37.467 RuntimeTest[3189:156810] MyClass is responsed to protocol NSCoding
2014-10-22 19:41:37.468 RuntimeTest[3189:156810] ======================================
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末击碗,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子们拙,更是在濱河造成了極大的恐慌稍途,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件砚婆,死亡現(xiàn)場(chǎng)離奇詭異械拍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)装盯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)坷虑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人埂奈,你說(shuō)我怎么就攤上這事迄损。” “怎么了账磺?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵芹敌,是天一觀的道長(zhǎng)共屈。 經(jīng)常有香客問(wèn)我,道長(zhǎng)党窜,這世上最難降的妖魔是什么拗引? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮幌衣,結(jié)果婚禮上矾削,老公的妹妹穿的比我還像新娘。我一直安慰自己豁护,他們只是感情好哼凯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著楚里,像睡著了一般断部。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上班缎,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天蝴光,我揣著相機(jī)與錄音梗脾,去河邊找鬼瘪吏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛忌傻,可吹牛的內(nèi)容都是我干的沉唠。 我是一名探鬼主播疆虚,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼满葛!你這毒婦竟也來(lái)了径簿?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嘀韧,失蹤者是張志新(化名)和其女友劉穎篇亭,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體乳蛾,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡暗赶,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年鄙币,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肃叶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡十嘿,死狀恐怖因惭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情绩衷,我是刑警寧澤蹦魔,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布激率,位于F島的核電站,受9級(jí)特大地震影響勿决,放射性物質(zhì)發(fā)生泄漏乒躺。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一低缩、第九天 我趴在偏房一處隱蔽的房頂上張望嘉冒。 院中可真熱鬧,春花似錦咆繁、人聲如沸讳推。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)银觅。三九已至,卻和暖如春坏为,著一層夾襖步出監(jiān)牢的瞬間究驴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工匀伏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留纳胧,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓帘撰,卻偏偏與公主長(zhǎng)得像跑慕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摧找,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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