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. ASP.NET Core 下的依赖注入(一)

    本文介绍利用 Microsoft.Extensions.Configuration.Binder.dll 来实现超级简单的注入. 1. appsettings.json 中定义配置 假设我们有如下配置 ...

  2. ASP.NET Core 2.1与2.2 SignalR CORS 跨域问题

    将 SignalR 集成到 ASP.NET Core api 程序的时候,按照官方 DEMO 配置完成,本地访问没有问题,但是发布之后一直报跨域问题,本地是这样设置的: Asp.net core 2. ...

  3. [翻译] ASP.NET Core 2.2 正式版发布

    本文为翻译,原文地址:https://blogs.msdn.microsoft.com/webdev/2018/12/04/asp-net-core-2-2-available-today/ 我(文章 ...

  4. 在Bootstrap开发框架中使用Grid++报表

    之前在随笔<在Winform开发中使用Grid++报表>介绍了在Winform环境中使用Grid++报表控件,本篇随笔介绍在Bootstrap开发框架中使用Grid++报表,也就是Web环 ...

  5. Activiti开发案例之代码生成工作流图片

    图例 环境 软件 版本 SpringBoot 1.5.10 activiti-spring-boot-starter-basic 6.0 生成代码 以下是简化代码: /** * 查看实例流程图,根据流 ...

  6. mange

    from flask import Flask app = Flask(__name__) manager = Manager(app) 1. 重写Command class ShellCommand ...

  7. day07(数据类型的相互转换 ,字符编码)

    一,复习: ''' 1,深浅拷贝 ls = [1,'a',[10]] 值拷贝:直接赋值 ls1 = ls,ls中的任何值发生改变,ls1也随之发生改变 浅拷贝:通过copy()方法 ls2 = ls. ...

  8. python + django + echart 构建中型项目

    1. python生产环境, 多层modules 导入问题: 多个modules 如何导入不同级别的包: 在每个modules下新建 __init__.pyimport os, sys dir_myt ...

  9. 定时任务调度工作(学习记录 三)timer其他重要函数

    TimerTask的两个重要函数: 1.cancel() 作用: 取消当前TimerTask里的任务 演示: 先在继承了TimerTask的类中添加一个计时器,然后在run方法中合适的位置添加canc ...

  10. Android数据库优化

    1.索引 简单的说,索引就像书本的目录,目录可以快速找到所在页数,数据库中索引可以帮助快速找到数据,而不用全表扫描,合适的索引可以大大提高数据库查询的效率.(1). 优点大大加快了数据库检索的速度,包 ...