【iOS/runtime/001】

介绍消息转发的机制

消息转发的条件

  • 如何创建demo: OC 头文件中有方法名称,没有方法实现的时候会触发消息转发机制;
  • 从子类 isa 的 methodlist 中开始找方法实现,一直找到 rootClass, 如果没有找到则触发消息转发机制;

消息转发类型

  1. 动态转发
// 动态转发(添加一个方法实现)
+ (BOOL)resolveInstanceMethod:(SEL)sel
  1. 快速转发
// 快速转发(创建一个备用接受者)
- (id)forwardingTargetForSelector:(SEL)aSelector 
  1. 慢速转发
// 慢速转发 (创建方法签名,调用下面一个方法)
// 1.方法签名;2.消息转发;两个方法配合使用
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 
- (void)forwardInvocation:(NSInvocation *)anInvocation

动态转发

为方法添加一个实现
v@:@

v返回值是 void;
@方法名称是一个object
:第一个参数标识
@第一个参数是一个object

+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSLog(@"%s", __func__);
    // 1. 匹配方法;
    NSString *methodName = NSStringFromSelector(sel);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return class_addMethod(self, sel, (IMP)sendMessage, "v@:@");
    }
    return NO;
}
void sendMessage(id self, SEL _cmd, NSString* msg) {
    NSLog(@"---%@", msg);
}

快速转发

为方法创建一个备用接受者

// 快速转发(创建一个备用接受者)
- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"%s", __func__);
    NSString *methodName = NSStringFromSelector(aSelector);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return [SpareWheel new];
    }
    return [super forwardingTargetForSelector:aSelector];
}

慢速转发

为方法添加一个签名
获取方法编号,并给方法找一个处理者

// 慢速转发 (创建方法签名,调用下面一个方法)
// 1.方法签名;2.消息转发;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSLog(@"%s", __func__);
    NSString *methodName = NSStringFromSelector(aSelector);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = [anInvocation selector];
    SpareWheel *tempObj = [SpareWheel new];
    if ([tempObj respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:tempObj];
    }
    [super forwardInvocation:anInvocation];
}

慢速转发以后防止崩溃

// 为应用崩溃做过什么事情, 加强 app 的健壮性
- (void)doesNotRecognizeSelector:(SEL)aSelector {
    NSLog(@"找不动方法");
}

相关代码

需要引如头文件 #import <objc/runtime.h> #import <objc/message.h>

  • 测试代码
    1、导入头文件<objc/message.h>
    2、设置enable strict checking of obc_msgSend calls为NO(否则objc_msgSend的参数会报错)
objc_msgSend([Person new], @selector(sendMessage:), @"helloMessage");
  • 相关代码
@implementation Person

// 动态转发(添加一个方法实现)
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    NSLog(@"%s", __func__);
    // 1. 匹配方法;
    NSString *methodName = NSStringFromSelector(sel);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return class_addMethod(self, sel, (IMP)sendMessage, "v@:@");
    }
    return NO;
}

// 快速转发(创建一个备用接受者)
- (id)forwardingTargetForSelector:(SEL)aSelector {
    NSLog(@"%s", __func__);
    NSString *methodName = NSStringFromSelector(aSelector);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return [SpareWheel new];
    }
    return [super forwardingTargetForSelector:aSelector];
}

// 慢速转发 (创建方法签名,调用下面一个方法)
// 1.方法签名;2.消息转发;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSLog(@"%s", __func__);
    NSString *methodName = NSStringFromSelector(aSelector);
    if ([methodName isEqualToString:@"sendMessage:"]) {
        return [NSMethodSignature signatureWithObjCTypes:"v@:@"];
    }
    return [super methodSignatureForSelector:aSelector];
}

- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = [anInvocation selector];
    SpareWheel *tempObj = [SpareWheel new];
    if ([tempObj respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:tempObj];
    }
    [super forwardInvocation:anInvocation];
}
// 为应用崩溃做过什么事情, 加强 app 的健壮性
- (void)doesNotRecognizeSelector:(SEL)aSelector {
    NSLog(@"找不动方法");
}

void sendMessage(id self, SEL _cmd, NSString* msg) {
    NSLog(@"---%@", msg);
}

//-(void)sendMessage:(NSString *)nickname {
//    NSLog(@"%s-%@", __func__, nickname);
//}

@end
@implementation SpareWheel
-(void)sendMessage:(NSString *)nickname {
    NSLog(@"%s-%@", __func__, nickname);
}
@end

面试相关问题

  1. 消息转发机制?
    从子类的 isa 中 的 methodlist 获取实现方法,一直向上,直到rootclass;
    如果没有找到实现方法,则进入消息转发机制;
  2. 消息转发过程?
    动态转发(创建实现),快速转发(创建备用接受类),慢速转发(创建签名,并找一个处理者)
  3. 为app崩溃做过一些什么事情,加强app 的健壮性?
    - (void)doesNotRecognizeSelector:(SEL)aSelector
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值