说到Runtime, 一直是很多(极少)人的软肋,含含糊糊的认知,被别人问到的时候,此题超纲... 将来跳槽粗去面试遇到 估计也会尴尬收场,届时估计真会让你36D的胸口一阵绞痛
推荐参考:
Method Swizzling原理:(http://blog.csdn.net/yiyaaixuexi/article/details/9374411
http://blog.sina.com.cn/s/blog_916e0cff0101ghxu.html
- Runtime介绍
Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西;runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者。Objective-c是一门编译型、动态语言(这里强调下oc是静态类型语言),这在开发语言中是并多见的,一般的动态语言多为解释性语言。OC之所以能够做到即使编译型语言,又是动态语言。就是得益于RunTime机制。
- 学习Runtime的意义
了解编程语言的可能性,对于语言的特性掌握的越多,语感就越好,技术视野的拓展和抽象设计的能力也就越强。
-
常见的使用场景
(还可以遍历属性 自定义对象序列化 归档 解档)
- 常用方法介绍
主要使用的函数定义在message.h和runtime.h这两个文件中, 在message.h中主要包含了一些向对象发送消息的函数,这是OC对象方法调用的底层实现。使用时,需要导入文件:
#import <objc/message.h>
#import <objc/runtime.h>
函数的定义
对对象进行操作的方法一般以object_开头
对类进行操作的方法一般以class_开头
对类或对象的方法进行操作的方法一般以method_开头
对成员变量进行操作的方法一般以ivar_开头
对属性进行操作的方法一般以property_开头开头
对协议进行操作的方法一般以protocol_开头
对于以objc_开头的方法,则是runtime最终的管家,可以获取内存中类的加载信息,类的列表,关联对象和关联属性等操作。
列举一些常用功能
1>、class_copyPropertyList 获取一份拷贝的成员列表数组;
2>、property_getName获取成员名称;
3>、class_getInstanceVariable 获取成员对象的Ivar;
4>、object_getIvar从Ivar对象中取值;
5>、object_setIvar赋值函数;
6>、objc_msgSend : 给对象发送消息;
7>、class_copyMethodList : 遍历某个类所有的方法
8>、class_copyIvarList : 遍历某个类所有的成员变量
9>、class_…..
- 具体代码实现
// 使用runtime对当前的应用中加载的类进行打印
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
unsigned int count = 0;
Class *classes = objc_copyClassList(&count);
for (int i = 0; i < count; i++) {
const char *cname = class_getName(classes[i]);
printf("%s\n", cname);
}
}
查看控制台输出
方法交换的使用,此处例子使用方法交换改变字体大小
创建UIFont的分类:#import "UIFont+Multi.h",通过重写load方法实现:
+ (void)load {
Method method0 = class_getClassMethod(self, @selector(systemFontOfSize:));
Method method1 = class_getClassMethod(self, @selector(ct_systemFontOfSize:));
method_exchangeImplementations(method0, method1);
}
+ (UIFont *)ct_systemFontOfSize:(CGFloat)fontSize {
NSString * size = [[NSUserDefaults standardUserDefaults] objectForKey:@"fontSizeIBDP"];
if ([CTStringUtils isBlankString:size]) {
size = @"0";
}
int sizeFont = [size intValue];
return [self ct_systemFontOfSize:fontSize+sizeFont];
}