最近遇到个线上问题,几百年没动过的模块出现了闪退现象,看了一个Crash log,都闪退在同一个问题上:
[__NSCFNumber length]: unrecognized selector sent to instance 0xb000000000000003
查看友盟错误统计列表,错误也均为同一个:
导致该问题原因:
- 先前与服务器接口定义为string类型的数据在iOS本地收到的是NSNumber类型(元凶)
- 调用UILabel对象setText:方法时,若将nil或非NSString类型对象赋值,Crash 现象发生(本地未做容错)
解决办法:
首先解决服务器数据类型不匹配问题。
对UILabel进行扩展
UILabel+Safe.m代码如下:
#import "UILabel+Safe.h"
#import "NSObject+SafeSwizzle.h"
@implementation UILabel (Safe)
+ (void)load{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self exchangeInstance:[UILabel class] selector:@selector(setText:) withSwizzledSelector:@selector(safe_setText:)];
});
}
- (void)safe_setText:(NSString *)text{
if(!text){
text = @"";
}
if(![text isKindOfClass:[NSString class]]){
text = [NSString stringWithFormat:@"%@", text];
}
// invoke originalimplemention
[self safe_setText:text];
}
@end
保证Category文件在工程中即可,不需要import。原先label.text = 赋值方法即使使用非NSString类型的对象或nil也不会Crash了
UILabel *label = [[UILabel alloc]init];
label.text = @(1);//运行奔溃
[self.view addSubview:label];