解决因为NSNull类型导致出现的unrecognized selector sent to instance问题

问题描述:因为objc是动态语言,对象的类型在运行时才会被确认,所以很容易出现一个定义为NSString类型的变量,在运行时的类型变成了NSNull,从而导致如下错误出现:-[NSNull stringByAppendingFormat:]: unrecognized selector sent to instance

下面介绍一下解决这个问题的思路

首先我们知道objc提供了消息转发机制,可以挽救当一个类调用了不存在的方法时,给你挽救的机会。我们就可以利用这个机制来拯救这个错误。

我们通过创建一个NSNull的分类,然后重写- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector和- (void)forwardInvocation:(NSInvocation *)anInvocation两个方法

1、在methodSignatureForSelector方法体中我们需要遍历系统中所有注册的iOS类,然后找到可以执行aSelector的类,并返回这个类的该aSelector的方法签名对象。

这里涉及以下几点:

a、遍历所有的已注册的类,利用runtime的objc_getClassList或objc_copyClassList

b、排除那些非继承自NSObject的类

c、对过滤后的类缓存,以及类对应的签名也要进行缓存,这里是为了提高查找效率

2、在forwardInvocation里如下:

1 - (void)forwardInvocation:(NSInvocation *)anInvocation{
2     anInvocation.target = nil;
3     [anInvocation invoke];
4 }

这里利用了objc的对象值为null的对象调用任何方法都会不执行并不报错的特点,将调用者target的值设置为null即可。

下面是获取方法签名的具体代码:

 1 - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
 2     @synchronized([self class])
 3     {
 4         //look up method signature
 5         NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
 6         if (!signature)
 7         {
 8             //not supported by NSNull, search other classes
 9             static NSMutableSet *classList = nil;
10             static NSMutableDictionary *signatureCache = nil;
11             if (signatureCache == nil)
12             {
13                 classList = [[NSMutableSet alloc] init];
14                 signatureCache = [[NSMutableDictionary alloc] init];
15
16                 //get class list
17                 int numClasses = objc_getClassList(NULL, 0);
18                 Class *classes = (Class *)malloc(sizeof(Class) * (unsigned long)numClasses);
19                 numClasses = objc_getClassList(classes, numClasses);
20
21                 //add to list for checking
22                 c
23                 for (int i = 0; i < numClasses; i++)
24                 {
25                     //determine if class has a superclass
26                     Class someClass = classes[i];
27                     Class superclass = class_getSuperclass(someClass);
28                     while (superclass)
29                     {
30                         if (superclass == [NSObject class])
31                         {
32                             [classList addObject:someClass];
33                             break;
34                         }
35                         [excluded addObject:NSStringFromClass(superclass)];
36                         superclass = class_getSuperclass(superclass);
37                     }
38                 }
39
40                 //remove all classes that have subclasses
41                 for (Class someClass in excluded)
42                 {
43                     [classList removeObject:someClass];
44                 }
45
46                 //free class list
47                 free(classes);
48             }
49
50             //check implementation cache first
51             NSString *selectorString = NSStringFromSelector(aSelector);
52             signature = signatureCache[selectorString];
53             if (!signature)
54             {
55                 //find implementation
56                 for (Class someClass in classList)
57                 {
58                     if ([someClass instancesRespondToSelector:aSelector])
59                     {
60                         signature = [someClass instanceMethodSignatureForSelector:aSelector];
61                         break;
62                     }
63                 }
64
65                 //cache for next time
66                 signatureCache[selectorString] = signature ?: [NSNull null];
67             }
68             else if ([signature isKindOfClass:[NSNull class]])
69             {
70                 signature = nil;
71             }
72         }
73         return signature;
74     }
75 }

原文地址:https://www.cnblogs.com/zbblog/p/12120413.html

时间: 2024-11-03 01:59:59

解决因为NSNull类型导致出现的unrecognized selector sent to instance问题的相关文章

(未解决)[NSNull intValue]: unrecognized selector sent to instance 0x375c9860

今天遇到这个问题,程序崩溃了……日志如下: -[NSNull intValue]: unrecognized selector sent to instance 0x375c9860*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull intValue]: unrecognized selector sent to instance 0x375c9860' ***

出现“unrecognized selector sent to instance”问题原因之一及解决方法。

? 对于iPhone开发初学者来说,很想实现自己在iPhone上的第一个小程序,准备工作就绪侯就信心满满的开始了!一般来说大家可能都是从Hello World做起吧. 反正我是的,:),如果按照文档上的说明去做,一般也不会出现什么问题.也建议初学者这样开始,毕竟会增强我们自己的信心. 但是当我们自己独立去做一个Button实现响应事件的小程序的时候,有时候确给我们出现了一点点小问题.也就是我题目所说的.下边我就列出出现此问题的 错误代码以及解决方式. code: [cpp] view plain

-[__NSCFNumber length]: unrecognized selector sent to instance 崩溃解决

崩溃原因是由于:获取JSON数据后存放在默认的NSMutableArry里,NSMutableArry是存放id类型的, uiTableViewCellMakeMoneyCustomCell.uiLabelActiveCountPoint.text=[nsMutableArryAllheActivesCountPoints objectAtIndex:indexPath.row]; 使用时引起类型不一致: 转化一下就可以了 uiTableViewCellMakeMoneyCustomCell.u

CRASH: -[NSNull length]: unrecognized selector sent to instance错误的处理办法

开发中从后台请求数据,返回如下: 2014-12-05 16:44:52.535 掌麦[6984:613] getDefaultAddress: reuslt == { item =     { data =         { address = "<null>"; area = "<null>"; city = "<null>"; name = ""; phone = 185030513

xcode开发中遇到unrecognized selector sent to instance 0x........的解决方法

首先贴一下问题代码 1 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 2 if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 3 UIButton *numberButton = [UIButton buttonWithType:UIButtonTypeCustom]; 4 numbe

Unrecognized Selector Sent to Instance问题之诱敌深入关门打狗解决办法

? MAY 17TH, 2014 前不久在微博上看到一篇文章,<UNRECOGNIZED SELECTOR SENT TO INSTANCE 问题快速定位的方法>?其中讲了iOS unrecognized selector sent to instance问题的快速定位方法,方法是不错的,但是实际测试发现文中的方法并非万能,从我自身的经历以及文中的评论看都有不能解决的情况. 出现unrecognized selector sent to instance问题,大部分是因为对象被提前释放,指针变

[__NSCFNumber isEqualToString:]: unrecognized selector sent to instance 0x7a97d4c0&#39;报错

今天接口由get换成post,我去改进行登录但出现了这个错误,首先出错先看能不能与服务器交互,能不能获得数据,其次,获得的数据是不是你想要的,记住,首先出错要想到是自己的问题,还有就是程序崩了要学会自己解决,打断点找原因,一步步跟,看是哪里出了问题 我这个问题一看就是拿了NSCFNumber类型和NSString类型做了比较,由于不会响应isEqualToString方法而报错,所以只要转换一下就可以了 NSString *factory_id = [NSString stringWithFor

利用objc的runtime来定位次线程中unrecognized selector sent to instance的问题

昨天遇到一个只有一行错误信息的问题: -[NSNull objectForKey:]: unrecognized selector sent to instance 0x537e068 由于这个问题发生在次线程,所以没有太有用的堆栈信息,而是只有简单的SIGABRT信息: 考虑到unrecognized selector sent to instance这类问题是由于向某个对象发送了未实现的消息,这个过程大致如下(图片摘自这里): 参考Objective-C的对象模型: struct objc_

unrecognized selector sent to instance

[iOS] Error Fixed : [__NSArrayI addObject:]: unrecognized selector sent to instance 当我创建了一个NSMutableArray 对象的时候 @property (nonatomic,copy)NSMutableArray *children; 然后通过addObject运行就会报错,[__NSArrayI addObject:]: unrecognized selector sent to instance 解决