1.

#import "UIView+Test.h"
#import <objc/runtime.h> @implementation UIView (Test) + (BOOL)resolveInstanceMethod:(SEL)sel {
return NO;
} - (id)forwardingTargetForSelector:(SEL)aSelector {
// NSString *sel = NSStringFromSelector(aSelector); { //
Class class = objc_allocateClassPair(NSClassFromString(@"NSObject"),"AvoidCrashTarget",);
class_addMethod(class, aSelector, class_getMethodImplementation([self class], @selector(avoidCrashAction)), "@@:"); id tempObject = [[class alloc] init];
return tempObject;
} return [super forwardingTargetForSelector:aSelector];
} - (NSObject *)avoidCrashAction {
return nil;
} @end

在Objective-C中,在调用对象的某个方法时,其实是在向这个对象发送消息。系统会查看这个对象能否接收该消息,如果不能,则会进行消息转发,消息转发最多三个步骤(注:如果前一步成功处理了消息,那么就不会走到下一步):

  1. 调用resolveInstanceMethod:resolveClassMethod:来决定是否动态添加方法。如果动态添加,则消息得到处理,消息转发结束;否则,进入下一步。

  2. 调用forwardingTargetForSelector:来确定能不能把这条消息转给其他接收者处理,如果返回一个非self的对象,则会把消息发送给该对象,消息转发结束;否则,进入下一步。

  3. 通过methodSignatureForSelector:方法获取签名,如果签名为nil,则消息无法处理,抛出异常;否则,调用forwardInvocation:方法,调用成功则消息转发结束,调用失败则消息无法处理,抛出异常。

https://github.com/mytcer/ios-docs-cn/blob/384b8a4aba5956fe20bb290a283757274f2a5ba6/Articles/runtime/message_forwarding.md

id GetterName(id self, SEL cmd) {
return objc_getAssociatedObject(self, cmd);
} void SetterName(id self, SEL cmd, NSString *value) {
NSString *sel = NSStringFromSelector(cmd);
NSString *key = [sel substringWithRange:NSMakeRange(, sel.length - )].lowercaseString;
objc_setAssociatedObject(self, NSSelectorFromString(key), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} if (sel == @selector(name)) {
// "@@:"的意思:
// 第一个字符表示函数的返回值类型,"@"表示GetterName函数的返回值类型为id
// 后面的字符表示函数的参数类型,"@:"表示GetterName函数接收两个参数,
// "@"表示参数类型为id,":"表示参数类型为SEL
class_addMethod(self, sel, (IMP)GetterName, "@@:");
return YES;
}
if (sel == @selector(setName:)) {
// "v@:@"的意思:
// "v"表示SetterName函数的返回值类型为void
// "@:@"参见上面
class_addMethod(self, sel, (IMP)SetterName, "v@:@");
return YES;
}

2.

给`NSNull`创建一个分类,并在.m中实现:

#import "NSNull+safe.h"
@implementation NSNull (safe)
#define pLog
#define JsonObjects @[@"",@0,@{},@[]]
- (id)forwardingTargetForSelector:(SEL)aSelector {
for (id jsonObj in JsonObjects) {
if ([jsonObj respondsToSelector:aSelector]) {
#ifdef pLog
NSLog(@"NULL出现啦!这个对象应该是是_%@",[jsonObj class]);
#endif
return jsonObj;
}
}
return [super forwardingTargetForSelector:aSelector];
}

https://www.jianshu.com/p/c5bdd6f7a68c

第31月第17天 resolveInstanceMethod的更多相关文章

  1. ADO.NET数据访问基础与综合应用2020年10月31日20:17:09学习笔记

    四.创建数据表 1.数据表的名称. 2.表中的字段名.数据类型.是否可以为空.字段的约束.必备的字段(通常会有一个ID,表示实体的唯一性:可以直接手写,也可以使用种子标识自动生成,给定起始值,给定增长 ...

  2. 第31月第25天 xcode debug 限制uitextfiled输入

    1.xcode debug 了解了每个设置的意思,个人觉得对于一个普通的app来说可以这样配置这些设置: Generate Debug Symbols:DEBUG和RELEASE下均设为YES(和Xc ...

  3. 第31月第19天 NV12

    1. //设置CIContext,并从CIImage -> CGImage -> UIImage CIContext *context = [CIContext contextWithOp ...

  4. 第31月第15天 -fembed-bitcode

    1. 确保打包的时候使用的是fembed-bitcode, 而不是fembed-bitcode-maker fembed-bitcode-maker:只是简单的标记一下在archive出来的二进制中b ...

  5. 第31月第10天 tableview头部空白 Other Linker Flags rtmp

    1.ios10 tableview头部空白 if (@available(iOS 11.0, *)) { self.tableView.contentInsetAdjustmentBehavior = ...

  6. 第31月 第9天 责任链AppDelegate

    1.AppDelegate 到这里我们把解决方案再明确一下:把 AppDelegate 的调用解耦成一个 责任链 模型.并且满足以下特征: 每个模块都可以无限制的实现 AppDelegate 的方法. ...

  7. 第27月第17天 objc_msgSendSuper

    1.objc_msgSendSuper super 的含义,消息转发会调用 objc_msgSendSuper, 就是 去父类的方法列表中找到 initWithFrame:这个方法,然后调用,调用的主 ...

  8. 第25月第17天 django rest framwork authentication /tmp/mysql.sock

    1.authentication https://www.django-rest-framework.org/api-guide/authentication/#authentication 2.dj ...

  9. 第20月第17天 mvvm 多次点击push -ObjC

    1. 响应式库EasyReact建成后,为了能使其得到更好的利用,更好地降低使用的理解和学习成本,臧成威老师又带领团队开发了基于响应式的MVVM框架:EasyMVVM. https://www.jia ...

随机推荐

  1. 教你在浏览器里做出EXCEL的效果

    在浏览器里做出EXCEL的效果,复制.粘贴.设置公式.双击编辑等效果,如果自己开发的话,比较麻烦,建议使用成熟的插件.这里介绍使用智表ZCELL插件,实现用户快捷操作. 首先下载插件,引入到页面中,一 ...

  2. 【spring源码分析】IOC容器初始化(六)

    前言:经过前几篇文章的讲解,我们已经得到了BeanDefinition,接下来将分析Bean的加载. 获取Bean的入口:AbstractApplicationContext#getBean publ ...

  3. 一款回到顶部的 jQuery 插件,支持 Div 中的滚动条回到顶部

    前言 今天在网上搜索“回到顶部”的 jQuery 插件,网上有很多,但是大部分都不支持让 Div 中的滚动条回到顶部.于是乎,不放弃,自己参考 Github 上的一个 jQuery 插件,经过自己的修 ...

  4. python 提取pdf文字

    安装pdfminer 库 windows 下安装pdfminer3k pip install pdfminer3k Liunx 下安装pdfminer pip install pdfminer 代码 ...

  5. 【原创】小说:我是一条DQL

    SQL执行流程图如下 本文改编自<高性能Mysql>,烟哥用小说的形式来讲这个内容. 序章 自我介绍 我是一条sql,就是一条长长的字符串,不要问我长什么样,因为我比较傲娇. 额~~不是我 ...

  6. python全局解释器GIL

    1.什么是进程: 进程是竞争计算机资源的基本单位.对于单核CPU来讲,同一时间只能有一个进程在运行,所以当我们开启多个应用时,操作系统需要根据进程调度算法去在不同的应用程序之间切换,而不同的进程之间切 ...

  7. git@github.com: Permission denied (publickey).////remote: Permission to xxx/test.git denied to xxx.等权限问题

    Error msg git@github.com: Permission denied (publickey) 或者: remote: Permission to xxx/test.git denie ...

  8. nginx基础之【study one】

    Nginx是种代理服务器,即可以作为反向代理服务器.邮件服务器等HTTP服务器,支持很多第三方模块扩展,如GZip.SSL.FastCGI. 最常用的功能有Http反向代理.负载均衡和Web缓存: 1 ...

  9. Python Scrapy项目创建(基础普及篇)

    在使用Scrapy开发爬虫时,通常需要创建一个Scrapy项目.通过如下命令即可创建 Scrapy 项目: scrapy startproject ZhipinSpider 在上面命令中,scrapy ...

  10. 重写URL

    更新网页url /***省略部分代码***/ function rewriteUrl(url) { if (url.substr(0, 1) === "/") { url = (r ...