Runtime

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.字典转模型

你可能感兴趣的:(Runtime)