1、什么是运行时(runtime):
1> runtime是一套底层的C语言API(包含很多强大实用的C语言数据类型、C语言函数)
2> 实际上,平时我们编写的OC代码,底层都是基于runtime实现的
* 也就是说,平时我们编写的OC代码,最终都是转成了底层的runtime代码(C语言代码)
2、运行时(runtime)有啥好处:
runtime有啥用?
1> 能动态产生一个类、一个成员变量、一个方法
2> 能动态修改一个类、一个成员变量、一个方法
3> 能动态删除一个类、一个成员变量、一个方法
3、常见的函数、头文件
#import <objc/runtime.h> : 成员变量、类、方法 Ivar * class_copyIvarList : 获得某个类内部的所有成员变量 Method * class_copyMethodList : 获得某个类内部的所有方法 Method class_getInstanceMethod : 获得某个实例方法(对象方法,减号-开头) Method class_getClassMethod : 获得某个类方法(加号+开头) method_exchangeImplementations : 交换2个方法的具体实现 #import <objc/message.h> : 消息机制 objc_msgSend(....)
4、运行时的(runtime)运用
4.1 获取所有成员属性
4.1.1 自定义一个类:
#import <Foundation/Foundation.h> @interface ICKPerson : NSObject /** 年龄 */ @property (nonatomic,assign) NSInteger age; /** 姓名 */ @property (nonatomic,copy) NSString * name; /** 身高 */ @property (nonatomic,assign) float height; /** 方法 */ - (void)eat; - (void)read; @end @implementation ICKPerson - (void)eat{} - (void)read{} @end
4.1.2 获取成员属性:
#import "ViewController.h" #import "ICKPerson.h" #import <objc/runtime.h> @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // 获取一个类的所有成员属性 unsigned int count = 0; Ivar *ivars = class_copyIvarList([ICKPerson class], &count); for (int i = 0; i<count; i++) { Ivar ivar = ivars[i]; // 获取属性名 const char *name = ivar_getName(ivar); // 获取属性类型 const char *class = ivar_getTypeEncoding(ivar); NSLog(@"name:%s class:%s",name,class); } // 释放ivars---C语言的在ARC中通过copy产生,需要手动释放 free(ivars); } @end
4.1.3 测试结果打印:
4.2 获取其所有内部方法
// 获取一个类的所有方法 unsigned int count = 0; Method *methods = class_copyMethodList([ICKPerson class], &count); for (int i = 0; i<count; i++) { // 取出对应的i 位置方法 Method method = methods[i]; SEL sel = method_getName(method); NSLog(@"%@",NSStringFromSelector(sel)); } free(methods);
打印结果:
4.3 交换两个方法的具体实现
4.3.1 交换方法
#import "ICKPerson.h" #import <objc/runtime.h> @implementation ICKPerson + (void)load { // 交换吃和度的方法 Method m1 = class_getInstanceMethod(self, @selector(eat)); Method m2 = class_getInstanceMethod(self, @selector(read)); method_exchangeImplementations(m1, m2); } - (void)eat{ NSLog(@"---eat"); } - (void)read{ NSLog(@"---read"); } @end
4.3.2 实现吃方法:
- (void)viewDidLoad { [super viewDidLoad]; ICKPerson *person = [[ICKPerson alloc] init]; [person eat]; }
// 打印结果
4.3.3 实现读方法:
- (void)viewDidLoad { [super viewDidLoad]; ICKPerson *person = [[ICKPerson alloc] init]; [person read]; }
// 打印结果