Runtime消息转发机制

没办法,哥们,我真的需要你来给我做这件事。你可以找你的兄弟去帮忙,然后给我结果就好了。

然后这哥们就告诉了你,他找不到方法的时候,应该怎么能拿到结果。

iOS对象找不到方法,系统调用机制


  1. 调用resolveInstanceMethod:方法 (或 resolveClassMethod:)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod。如果仍没实现,继续下面的动作。

  2. 调用forwardingTargetForSelector:方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。

  3. 调用methodSignatureForSelector:方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:

  4. 调用forwardInvocation:方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。

  5. 调用doesNotRecognizeSelector: ,默认的实现是抛出异常。如果第3步没能获得一个方法签名,执行该步骤。

iOS如何消息转发


1.首先在类方法列表中没有找到方法,那么系统会调用resolveInstanceMethod或者resolveClassMethod,让你动态添加方法实现。

/**

*  通过这个方法来实现动态添加方法

*

*  @param sel 没有实现的方法

*

*  @return 返回YES处理方法或者NO转发到下一步

*/

+(BOOL)resolveInstanceMethod:(SEL)sel{

//方法名

NSString *selStr = NSStringFromSelector(sel);

if ([selStr isEqualToString:@“XXXX1”]) {

//增加你要实现的方法

class_addMethod(self, sel, (IMP)AAAA, “@@:”);

return YES;

}

if ([selStr isEqualToString:@“XXXX2:”]) {

class_addMethod(self, sel, (IMP)BBBB, “v@😡”);

return YES;

}

return [super resolveInstanceMethod:sel];

}

/**

*  这个方法实现XXXX2的转发

*

*  @param self  对象

*  @param cmd   方法

*  @param value 传入的值

*/

void BBBB(idself, SEL cmd,id value){

}

/**

*  这个方法用于XXXX1的转发

*

*  @param self 对象自己

*  @param cmd  方法名

*

*  @return 返回得到的值

*/

id AAAA(idself, SEL cmd){

}

顺便说一下: class_addMethod方法的使用

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

参数说明:

cls:被添加方法的类

name:可以理解为方法名,这个貌似随便起名,比如我们这里叫sayHello2

imp:实现这个方法的函数

types:一个定义该函数返回值类型和参数类型的字符串,

types具体符号讲解:

例如 AAAA的参数 @@:

按顺序分别表示:

第一个参数@    表示返回值为id

返回类型int 用 i 表示 , 返回void用v表示

第二个参数@    表示参数self

还可以表示OC类型的参数

第三个参数:    表示SEL(_cmd)

2.如果第一个方法返回NO,转发进入下一步 forwardingTargetForSelector


/**

*  转发到另一个对象去处理,其他的下一步

*

*  @param aSelector 方法

*

*  @return 返回转发的处理对象或者nil

*/

-(id)forwardingTargetForSelector:(SEL)aSelector{

NSString *selStr =NSStringFromSelector(aSelector);

//如果是没有实现的方法,则处理转发

if ([selStrisEqualToString:@“Method1”]) {

//返回处理这个转发的对象

return MethodModel;

}else{

return [superforwardingTargetForSelector:aSelector];

}

}

3.如果没有转发对象,上一步返回未nil,则进行下一步转发。如果返回nil,doesNotRecognizeSelector报异常。

/**

*  是自己新建方法签名,再在forwardInvocation中用你要转发的那个对象调用这个对应的签名,这样也实现了消息转发。

*

*  @param aSelector 方法名

*

*  @return 返回一个签名

*/

-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{

NSMethodSignature *sig =nil;

NSString *selStr = NSStringFromSelector(aSelector);

最后

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中…(img-v6c1XYob-1715589855392)]

[外链图片转存中…(img-fHaiez14-1715589855393)]

[外链图片转存中…(img-gKVUDgyv-1715589855393)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值