认识
- Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事情放在了运行时来处理。
- 这种特性意味着Objective-C不仅需要一个编译器,还需要一个运行时系统来执行编译的代码,这个运行时系统就是Objc Runtime。
- Runtime库主要做下面两个时期:
- 封装:在这个库中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上一些额外的特性。这些结构体和函数被runtime函数封装后,我们就可以在程序运行时创建,检查,修改类和对象和它们的方法了。
- 找出方法的最终执行代码:当程序执行[object doSomething]时,会向消息接受者(object)发送一条消息(dosomething),runtime会根据消息接受者是否能响应消息而做出不同的反应。
能做什么?
- 动态创建函数、类、替换已有的函数
- 动态创建protocol、创建子类
- 了解runtime可以让你知道通过clang编译器,你的objective-C
代码转成了什么样c代码
类与对象数据结构、操作函数
这里有详细的介绍类与对象的数据结构和操作函数的文章,大家可以移驾,这里边有很全的介绍,下面是我学习的时候自己撸的代码github地址
这里必须看这个文章,比我要写的全面:http://blog.jobbole.com/79566/?utm_source=blog.jobbole.com&utm_medium=relatedPosts#article-comment
具体应用1:替换数组、字典的取值函数越界问题
在做iOS的时候,因为OC是运行时语言,往往在数组中去数值或者向字典中插入数值的时候,会有nil的现象,这种时候可以通过runtime来避免。项目源码github地址
具体应用2:黑魔法(Method Swizzing)
例如,我们想跟踪在程序中每一个view controller展示给用户的次数:当然,我们可以在每个view controller的viewDidAppear中添加跟踪代码;但是这太过麻烦,需要在每个view controller中写重复的代码。创建一个子类可能是一种实现方式,但需要同时创建UIViewController, UITableViewController, UINavigationController及其它UIKit中view controller的子类,这同样会产生许多重复的代码。
#import <objc/runtime.h>
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(xxx_viewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
@end
注意事项:
1:Swizzling应该总是在+load中执行
2:Swizzling应该总是在dispatch_once中执行