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,不进行断言检查。

上一篇下一篇

猜你喜欢

热点阅读