NSNull 的 Crash问题解决
2018-07-12 本文已影响0人
5c3c832f76b0
解决NSNull造成的crash问题
在我们的开发中,很多时候后台会返回null,到了我们iOS这一端,就成为了NSNull 对象,就会发生很多的crash现象.
只要解决此问题,需要将创建一个NSNull全局分类,然后加入以下代码即可
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@autoreleasepool {
[self tf_replaceWithOriginalMethod:@selector(length) replaceSelector:@selector(tf_length)];
[self tf_replaceWithOriginalMethod:@selector(integerValue) replaceSelector:@selector(tf_integerValue)];
[self tf_replaceWithOriginalMethod:@selector(objectForKey:) replaceSelector:@selector(tf_objectForKey:)];
[self tf_replaceWithOriginalMethod:@selector(objectAtIndex:) replaceSelector:@selector(tf_objectAtIndex:)];
}
});
}
+ (void)tf_replaceWithOriginalMethod:(SEL)originalSelector replaceSelector:(SEL)replaceSelector {
Class class = [self class];
//原来的方法
Method originalMethod = class_getInstanceMethod(class, originalSelector);
//替换的新方法
Method replaceMethod = class_getInstanceMethod(class, replaceSelector);
//先尝试給源SEL添加IMP,这里是为了避免源SEL没有实现IMP的情况
BOOL didAddMethod = class_addMethod(class,originalSelector,
method_getImplementation(replaceMethod),
method_getTypeEncoding(replaceMethod));
if (didAddMethod) {//添加成功:说明源SEL没有实现IMP,将源SEL的IMP替换到交换SEL的IMP
class_replaceMethod(class,replaceSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {//添加失败:说明源SEL已经有IMP,直接将两个SEL的IMP交换即可
method_exchangeImplementations(originalMethod, replaceMethod);
}
}
- (NSInteger)tf_length {
NSAssert(NO, @"null..");
return 0;
}
- (NSInteger)tf_integerValue {
NSAssert(NO, @"null..");
return 0;
}
- (id)tf_objectForKey:(id)key{
NSAssert(NO, @"null..");
return nil;
}
- (id)tf_objectAtIndex:(NSInteger)index{
NSAssert(NO, @"null..");
return nil;
}
注:由于下面的方法中,为了方便项目的调试,使用了断言.调试cocoa程序在程序出错时,不会马上停止。使用宏NSAssert可以让程序出错时马上抛出异常。在debug情况下,所有NSAssert都会被执行。在release下不希望NSAssert被执行,我们通常在release种将断言设置成禁用。
设置方法:在Build Settings菜单,找到Preprocessor Macros项,Preprocessor Macros项下面有一个选择,用于程序生成配置:Debug版和Release版。选择 Release项,设置NS_BLOCK_ASSERTIONS,不进行断言检查。