OC Runtime
什么是Runtime
RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用
消息转发机制流程
1.动态方法解析
对象在接收到未知的消息时,首先会调用所属类的类方法+resolveInstanceMethod:(实例方法)或 者+resolveClassMethod:(类方法)。在这个方法中,我们有机会为该未知消息新增一个”处理方法”“。不过使用该方法的前提是我们已经 实现了该”处理方法”,我们可以在运行时通过class_addMethod函数动态添加未知消息到类里面,让原来没有处理这个方法的类具有了处理这个方法的能力。
+(BOOL)resolveInstanceMethod:(SEL)sel
{
//从系统里匹配SEL,如没有就注册SEL
SEL systemSel = sel_registerName(sel_getName(sel));
//把所有未知的SEL指向dynamicMethodIMP的实现,让dynamicMethodIMP帮忙打印错误信息,但是程序不会Cash
class_addMethod(self,systemSel,(IMP)dynamicMethodIMP,"v@:");
return [super resolveClassMethod:systemSel];
}
2.备用接收者
如果在动态方法解析无法处理消息,则Runtime会继续调以下方法:
-(id)forwardingTargetForSelector:(SEL)aSelector
{
return [[Girl alloc] init];
}
3.完整转发
如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。
此时会调用以下方法:
//在这里产生方法签名,以确保NSInvocation能被转发的Girl类执行,不然的话会出现错误
-(NSMethodSignature*)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
if (!signature) {
if ([Girl instancesRespondToSelector:aSelector]) {
signature = [Girl instanceMethodSignatureForSelector:aSelector];
}
}
return signature;
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([Girl instancesRespondToSelector:anInvocation.selector]) {
[anInvocation invokeWithTarget:[[Girl alloc] init]];//将消息转发给Girl对象
}
}
-(id)forwardingTargetForSelector:(SEL)aSelector
{
return [[Girl alloc] init];
}
runtime 使用场景
1.发送消息
2.交换方法
+ (void)load {
/*
self:UIImage
谁的事情,谁开头 1.发送消息(对象:objc) 2.注册方法(方法编号:sel) 3.交互方法(方法:method) 4.获取方法(类:class)
Method:方法名
获取方法,方法保存到类
Class:获取哪个类方法
SEL:获取哪个方法
imageName
*/
// 获取imageName:方法的地址
Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));
// 获取wg_imageWithName:方法的地址
Method wg_imageWithNameMethod = class_getClassMethod(self, @selector(wg_imageWithName:));
// 交换方法地址,相当于交换实现方式
method_exchangeImplementations(imageNameMethod, wg_imageWithNameMethod);
}
3.动态添加方法
WGStudent *student = [[WGStudent alloc] init];
objc_msgSend(student, @selector(study));
4.给分类添加属性
通过关联实现
例子
UIButton * btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.tag = 100;
NSLog(@"%d",btn.tag);
objc_setAssociatedObject(self, &overviewKey, btn, OBJC_ASSOCIATION_RETAIN);
UIButton * btn1 = objc_getAssociatedObject(self, &overviewKey);
btn1.tag =111;
NSLog(@"%d",btn1.tag);
static char flashColorKey;
- (void) setFlashColor:(UIColor *) flashColor{
objc_setAssociatedObject(self, &flashColorKey, flashColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIColor *) getFlashColor{
return objc_getAssociatedObject(self, &flashColorKey);
}
5.字典转模型