一、前言
本文主要記錄如何用runtime 動態添加類 添加實例變量 添加方法等。項目中雖然很少用到,但是本著學習的態度,記錄下來以便學習。
順便給自己灌碗雞湯:搞 iOS 學算法有意義嗎?-唐巧。
本文Demo 地址:demo
二、切入正題
代碼走一遍
1、 添加一個集成NSObject的類 類名是MyClass
注意:調用的c語言的方法 所以不要使用@""表示字符串 應該使用""
Class MyClass = objc_allocateClassPair([NSObject class], "MyClass", 0);
2、增加實例變量
參數一、類名
參數二、屬性名稱
參數三、開辟字節長度
參數四、對其方式
參數五、參數類型 “@” 官方解釋 An object (whether statically typed or typed id) (對象 靜態類型或者id類型) 具體類型可參照官方文檔
return: BOOL 是否添加成功
BOOL isSuccess = class_addIvar(MyClass, "test", sizeof(NSString *), 0, "@");
// 三目運算符
isSuccess?NSLog(@"添加變量成功"):NSLog(@"添加變量失敗");
3、增加方法
給MyClass這個類添加方法;
參數一、類名
參數二、SEL 添加的方法名字
參數三、IMP指針 (IMP就是Implementation的縮寫,它是指向一個方法實現的指針,每一個方法都有一個對應的IMP)
參數四、其中types參數為"i@:@“,按順序分別表示:具體類型可參照官方文檔
i 返回值類型int,若是v則表示void
@ 參數id(self)
: SEL(_cmd)
@ id(str)
V@:表示返回值是void 帶有SEL參數 (An object (whether statically typed or typed id))
class_addMethod(MyClass, @selector(addMethodForMyClass:), (IMP)addMethodForMyClass, "V@:");
4、這里我們需要實現一個函數和一個方法
函數 //self和_cmd是必須的,在之后可以隨意添加其他參數
static void addMethodForMyClass(id self, SEL _cmd, NSString *test) {
// 獲取類中指定名稱實例成員變量的信息
Ivar ivar = class_getInstanceVariable([self class], "test");
// 獲取整個成員變量列表
// Ivar * class_copyIvarList ( Class cls, unsigned intint * outCount );
// 獲取類中指定名稱實例成員變量的信息
// 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:參數:%@",test);
NSLog(@"ClassName:%@",NSStringFromClass([self class]));
}
5、我們要實現這個方法
//這個方法實際上沒有被調用,但是必須實現否則不會調用addMethodForMyClass()方法
- (void)addMethodForMyClass:(NSString *)string {
}
6、接著第三步 開始創建MyClass對
id myObjc = [[MyClass alloc] init];
NSLog(@"%@",myObjc);
這個我們也可以通過發送消息創建對象
在OC中,我們對方法的調用都會被轉換成內部的消息發送執行對objc_msgSend方法的調用,掌握好消息發送,可以讓我們在編程中更方便靈活。
上面的id myObjc = [[MyClass alloc] init]; 我們可以通過runtime 消息發送objc_msgSend去實現
實現[MyClass alloc] 去開辟空間 并初始化
id myobjc = objc_msgSend(MyClass, @selector(alloc));
myobjc = objc_msgSend(myobjc, @selector(init));
下面我給屬性test賦值
NSString *str = @"我是test";
// 通過KVC的方式給myObj對象的test屬性賦值
[myobjc setValue:str forKey:@"test"];
// 如果不調用- (void)addMethodForMyClass:(NSString *)string 這個方法,就不會調用static void addMethodForMyClass(id self, SEL _cmd, NSString *test) 函數
[myobjc addMethodForMyClass:@"參數"];
通過上面的所有步驟 可以運行并且在函數addMethodForMyClass()打印確定這個類是不是創建成功
好了,今天就到這結束了,如果那里有錯誤,歡迎大家糾正!