没办法,哥们,我真的需要你来给我做这件事。你可以找你的兄弟去帮忙,然后给我结果就好了。
然后这哥们就告诉了你,他找不到方法的时候,应该怎么能拿到结果。
iOS对象找不到方法,系统调用机制
-
调用
resolveInstanceMethod:
方法 (或resolveClassMethod:
)。允许用户在此时为该 Class 动态添加实现。如果有实现了,则调用并返回YES,那么重新开始objc_msgSend
流程。这一次对象会响应这个选择器,一般是因为它已经调用过class_addMethod
。如果仍没实现,继续下面的动作。 -
调用
forwardingTargetForSelector:
方法,尝试找到一个能响应该消息的对象。如果获取到,则直接把消息转发给它,返回非 nil 对象。否则返回 nil ,继续下面的动作。注意,这里不要返回 self ,否则会形成死循环。 -
调用
methodSignatureForSelector:
方法,尝试获得一个方法签名。如果获取不到,则直接调用doesNotRecognizeSelector
抛出异常。如果能获取,则返回非nil:创建一个 NSlnvocation 并传给forwardInvocation:
。 -
调用
forwardInvocation:
方法,将第3步获取到的方法签名包装成 Invocation 传入,如何处理就在这里面了,并返回非ni。 -
调用
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前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**
[外链图片转存中…(img-9qHI9JEL-1714951886875)]
[外链图片转存中…(img-6bUIiRco-1714951886876)]
[外链图片转存中…(img-jjQodIYl-1714951886876)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!