一、前言
本文主要記錄如何用runtime 動(dòng)態(tài)添加類 添加實(shí)例變量 添加方法等选脊。項(xiàng)目中雖然很少用到杭抠,但是本著學(xué)習(xí)的態(tài)度,記錄下來(lái)以便學(xué)習(xí)恳啥。
順便給自己灌碗雞湯:搞 iOS 學(xué)算法有意義嗎偏灿?-唐巧。
本文Demo 地址:demo
二钝的、切入正題
代碼走一遍
1翁垂、 添加一個(gè)集成NSObject的類 類名是MyClass
注意:調(diào)用的c語(yǔ)言的方法 所以不要使用@""表示字符串 應(yīng)該使用""
Class MyClass = objc_allocateClassPair([NSObject class], "MyClass", 0);
2铆遭、增加實(shí)例變量
參數(shù)一、類名
參數(shù)二沿猜、屬性名稱
參數(shù)三枚荣、開辟字節(jié)長(zhǎng)度
參數(shù)四、對(duì)其方式
參數(shù)五啼肩、參數(shù)類型 “@” 官方解釋 An object (whether statically typed or typed id) (對(duì)象 靜態(tài)類型或者id類型) 具體類型可參照官方文檔
return: BOOL 是否添加成功
BOOL isSuccess = class_addIvar(MyClass, "test", sizeof(NSString *), 0, "@");
// 三目運(yùn)算符
isSuccess?NSLog(@"添加變量成功"):NSLog(@"添加變量失敗");
3橄妆、增加方法
給MyClass這個(gè)類添加方法;
參數(shù)一祈坠、類名
參數(shù)二呼畸、SEL 添加的方法名字
參數(shù)三、IMP指針 (IMP就是Implementation的縮寫颁虐,它是指向一個(gè)方法實(shí)現(xiàn)的指針,每一個(gè)方法都有一個(gè)對(duì)應(yīng)的IMP)
參數(shù)四卧须、其中types參數(shù)為"i@:@“另绩,按順序分別表示:具體類型可參照官方文檔
i 返回值類型int,若是v則表示void
@ 參數(shù)id(self)
: SEL(_cmd)
@ id(str)
V@:表示返回值是void 帶有SEL參數(shù) (An object (whether statically typed or typed id))
class_addMethod(MyClass, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
4花嘶、這里我們需要實(shí)現(xiàn)一個(gè)函數(shù)和一個(gè)方法
函數(shù) //self和_cmd是必須的笋籽,在之后可以隨意添加其他參數(shù)
static void addMethodForMyClass(id self, SEL _cmd, NSString *test) {
// 獲取類中指定名稱實(shí)例成員變量的信息
Ivar ivar = class_getInstanceVariable([self class], "test");
// 獲取整個(gè)成員變量列表
// Ivar * class_copyIvarList ( Class cls, unsigned intint * outCount );
// 獲取類中指定名稱實(shí)例成員變量的信息
// Ivar class_getInstanceVariable ( Class cls, const charchar *name );
// 獲取類成員變量的信息
// Ivar class_getClassVariable ( Class cls, const charchar *name );
// 返回名為test的ivar變量的值
id obj = object_getIvar(self, ivar);
NSLog(@"%@",obj);
NSLog(@"addMethodForMyClass:參數(shù):%@",test);
NSLog(@"ClassName:%@",NSStringFromClass([self class]));
}
5、我們要實(shí)現(xiàn)這個(gè)方法
//這個(gè)方法實(shí)際上沒(méi)有被調(diào)用,但是必須實(shí)現(xiàn)否則不會(huì)調(diào)用addMethodForMyClass()方法
- (void)addMethodForMyClass:(NSString *)string {
}
6椭员、接著第三步 開始創(chuàng)建MyClass對(duì)
id myObjc = [[MyClass alloc] init];
NSLog(@"%@",myObjc);
這個(gè)我們也可以通過(guò)發(fā)送消息創(chuàng)建對(duì)象
在OC中车海,我們對(duì)方法的調(diào)用都會(huì)被轉(zhuǎn)換成內(nèi)部的消息發(fā)送執(zhí)行對(duì)objc_msgSend方法的調(diào)用,掌握好消息發(fā)送隘击,可以讓我們?cè)诰幊讨懈奖沆`活侍芝。
上面的id myObjc = [[MyClass alloc] init]; 我們可以通過(guò)runtime 消息發(fā)送objc_msgSend去實(shí)現(xiàn)
實(shí)現(xiàn)[MyClass alloc] 去開辟空間 并初始化
id myobjc = objc_msgSend(MyClass, @selector(alloc));
myobjc = objc_msgSend(myobjc, @selector(init));
下面我給屬性test賦值
NSString *str = @"我是test";
// 通過(guò)KVC的方式給myObj對(duì)象的test屬性賦值
[myobjc setValue:str forKey:@"test"];
// 如果不調(diào)用- (void)addMethodForMyClass:(NSString *)string 這個(gè)方法,就不會(huì)調(diào)用static void addMethodForMyClass(id self, SEL _cmd, NSString *test) 函數(shù)
[myobjc addMethodForMyClass:@"參數(shù)"];
通過(guò)上面的所有步驟 可以運(yùn)行并且在函數(shù)addMethodForMyClass()打印確定這個(gè)類是不是創(chuàng)建成功
好了埋同,今天就到這結(jié)束了州叠,如果那里有錯(cuò)誤,歡迎大家糾正凶赁!