预防 app crash 之 unrecognized selector
处理unrecognized selector异常原因
假如封装一个方法,在其他模块调用该方法时,传入参数不匹配则crash。比如下面的方法:本应该传入的参数类型为NSMutableArray,如果传入的参数类型是NSArray,导致抛出 unrecognized selector异常
|
1
2
3
|
- (void)doSomethingWithArray:(NSMutableArray *)arr{
[arr addObject:@"123"];
}
|
当然,通过 参数类型判断 也可以避免问题的发生:
|
1
2
3
4
5
6
7
|
- (void)doSomethingWithArray:(NSMutableArray *)arr{
if ([arr isKindOfClass:[NSMutableArray class]]) {
[arr addObject:@"123"];
}else{
CrashOnSimulator(@"⚠️参数类型不对哦⚠️");
}
}
|
crash提醒:
123 void CrashOnSimulator(NSString *errorMsg) {if((TARGET_OS_SIMULATOR)){raise(SIGSTOP);}}
但是,有点地方可能忘记类型判断了怎么办,有全局拦截unrecognized selector 异常的方案吗?
分析 如何全局拦截unrecognized selector 异常

oc的消息发送机制咱们都熟悉了,通过superclass指针逐级向上查找该消息所对应的方法实现,如果遇到找不的方法,还有三次补救机制。我们可以通过上面三种方法中的一种,就可以避免unrecognized selector sent to instance
第一种方法:重写 NSObject 的forwardingTargetForSelector:
⚠️filter unrecoginze seletor of intance only
思路
- 创建一个接收未知消息的类,暂且称之为
Protector - 创建一个
NSObject的分类,在分类中重写forwardingTargetForSelector: ,在这个方法中截获未实现的方法,转发给Protector。并为Protector动态的添加未实现的方法,最后返回Protector的实例对象。 - 在分类中新增一个安全的方法实现,来作为
Protector接收到的未知消息的实现
代码
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
#import "NSObject+Protector.h"
#import <objc/runtime.h>
@implementation NSObject (Protector)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
- (id)forwardingTargetForSelector:(SEL)aSelector{
if ([self isCurrentClassInWhiteList]) {
[[self class] warningDeveloper:aSelector];
Class protectorCls = NSClassFromString(@"ProtectorClassName");
if (!protectorCls){
protectorCls = objc_allocateClassPair([NSObject class], "ProtectorClassName", 0);
objc_registerClassPair(protectorCls);
}
if (![self isExistSelector:aSelector inClass:protectorCls]){
class_addMethod(protectorCls, aSelector, [self safeImplementation:aSelector],[NSStringFromSelector(aSelector) UTF8String]);
}
Class Protector = [protectorCls class];
id instance = [[Protector alloc] init];
return instance;
} else {
return nil;
}
}
#pragma clang diagnostic pop
- (BOOL)isCurrentClassInWhiteList{
NSArray *classNameArray = @[@"NSNull",@"NSString",@"NSArray",@"NSDictionary",@"NSURL"];
for (NSString *className in classNameArray) {
if ([self isKindOfClass:NSClassFromString(className)]) {
return YES;
}
}
return NO;
}
- (BOOL)isExistSelector: (SEL)aSelector inClass:(Class)currentClass{
BOOL isExist = NO;
unsigned int methodCount = 0;
Method *methods = class_copyMethodList(currentClass, &methodCount);
for (int i = 0; i < methodCount; i++){
Method temp = methods[i];
SEL sel = method_getName(temp);
NSString *methodName = NSStringFromSelector(sel);
if ([methodName isEqualToString: NSStringFromSelector(aSelector)]){
isExist = YES;
break;
}
}
return isExist;
}
- (IMP)safeImplementation:(SEL)aSelector{
IMP imp = imp_implementationWithBlock(^(){
NSLog(@"PROTECTOR: %@ Done", NSStringFromSelector(aSelector));
});
return imp;
}
+ (void)warningDeveloper:(SEL)aSelector{
#if DEBUG
NSString *selectorStr = NSStringFromSelector(aSelector);
NSLog(@"PROTECTOR: -[%@ %@]", [self class], selectorStr);
NSLog(@"PROTECTOR: unrecognized selector \"%@\" sent to instance: %p", selectorStr, self);
NSLog(@"PROTECTOR: call stack: %@", [NSThread callStackSymbols]);
// @throw @"方法找不到";
#endif
}
@end
|
第二种方法:重写 NSObject 的methodSignatureForSelector(有些问题,下面有个最终版)
预防 app crash 之 unrecognized selector的更多相关文章
- reason: -[UIKBBlurredKeyView candidateList]: unrecognized selector sent to instance
reason: -[UIKBBlurredKeyView candidateList]: unrecognized selector sent to instance 发现上线的app一直会有这个cr ...
- ios unrecognized selector sent to instance出现的原因和解决方案
概述:造成unrecognized selector sent to instance iphone,大部分情况下是因为对象被提前release了,在你心里不希望他release的情况下,指针还在,对 ...
- 出现“unrecognized selector sent to instance”问题原因之一及解决方法。
对于iPhone开发初学者来说,很想实现自己在iPhone上的第一个小程序,准备工作就绪侯就信心满满的开始了!一般来说大家可能都是从Hello World做起吧. 反正我是的,:),如果按照文 ...
- [NSNull intValue]: unrecognized selector sent to instance 0x375c9860
今天遇到这个问题,程序崩溃了……日志如下: -[NSNull intValue]: unrecognized selector sent to instance 0x375c9860*** Termi ...
- IOS 错误 [UIWebView cut:]: unrecognized selector sent to instance
那在什么场景中会出现这种情况呢? 如果一个包含文字的输入元素有焦点,然后按钮的点击会导致输入失去焦点,然后接下来在输入时双按会重新得到焦点并从弹出bar中选择剪切复制粘贴,就会导致此error. 也就 ...
- iOS 程序报错:reason: [NSArrayI addObject:]: unrecognized selector sent to instance
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI ad ...
- unrecognized selector sent to instance 0x10b34e810
一个错误: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSURLEr ...
- Solve Error: 'NSInvalidArgumentException', reason: '-[UITableView mas_makeConstraints:]: unrecognized selector sent to instance 0x7fa5c402fa00'
下面是iOS开发用第三方库可能出现的错误,及其解决方法: 1. 'NSInvalidArgumentException', reason: '-[UITableView mas_makeConstra ...
- __NSArrayI removeObjectAtIndex:]: unrecognized selector sent to instance
同样是删除cell问题,帮我看看问题出现在哪,谢谢! 我的类文件myFile是继承UIViewController的(目的是为了能够在一个view里切换不同的tableView),在myFile.h中 ...
随机推荐
- Asp.Net Core WebAPI入门整理(三)跨域处理
一.Core WebAPI中的跨域处理 1.在使用WebAPI项目的时候基本上都会用到跨域处理 2.Core WebAPI的项目中自带了跨域Cors的处理,不需要单独添加程序包 3.使用方法简单 ...
- POJ 2718【permutation】
POJ 2718 问题描述: 给一串数,求划分后一个子集以某种排列构成一个数,余下数以某种排列构成另一个数,求这两个数最小的差,注意0开头的处理. 超时问题:一开始是得到一个数列的组合之后再从中间进行 ...
- JDK和CGLIB生成动态代理类的区别
关于动态代理和静态代理 当一个对象(客户端)不能或者不想直接引用另一个对象(目标对象),这时可以应用代理模式在这两者之间构建一个桥梁--代理对象. 按照代理对象的创建时期不同,可以分为两种: 静态代 ...
- optional
public class Test { public static void main(String[] args) { People people = new People(); Optional& ...
- 6-20 Ideal Path uva1599
第一个bfs很快 但是我第一次做还用了结构体 这题完全不需要 反而导致了代码非常乱 输入: 一开始我是用m二维数组储存颜色 vector path来储存路径 但是二维数组的下标是不够用的 ...
- 096实战 在windows下新建maven项目
1.拷贝settings到.m2文件下 2.修改文件 3.新建Project项目 4.转换为maven项目 config下转换 5.拷贝pom文件 <project xmlns="ht ...
- 用VScode代码调试Python
Python扩展支持许多类型的Python应用程序的调试,包括以下一般功能: 观看窗口 评估表达式 当地人 参数 扩大孩子 断点 条件断点 暂停(进入)正在运行的程序 自定义启动目录 要熟悉这些常规功 ...
- 使用metasploit做SNMP扫描和利用
使用MSF用于SNMP扫描 auxiliary/scanner/snmp/snmp_login 介绍 补充知识: 在执行SNMP扫描之前,需要了解几件事情.首先,“只读”和“读写”团体名(commun ...
- 【Ray Tracing The Next Week 超详解】 光线追踪2-7 任意长方体 && 场景案例
上一篇比较简单,很久才发是因为做了一些好玩的场景,后来发现这一章是专门写场景例子的,所以就安排到了这一篇 Preface 这一篇要介绍的内容有: 1. 自己做的光照例子 2. Cornell box画 ...
- 关于文档模式、DCOTYPE声明及严格模式
1.文档模式 文档模式的概念是由IE5.5引入,通过使用文档类型(DOCTYPE)切换实现的.不同的文档模式主要影响CSS内容的呈现,尤其是浏览器对盒模型的解析,但在某些情况下也会影响到JavaScr ...