iOS开发json解析崩溃的解决方案

2018-03-31  本文已影响0人  本本的开心牧场

在iOS开发中我们从接口获取的数据大多是json类型的,但是json转对象后总会出现一些NSNull类型,NSNull是个坑,因为他很可能会使我们的程序崩溃

我觉得对nil、Nil、NULL和[NSNull null]的区别不是很了解 可以去看下这篇文章https://www.jianshu.com/p/69a6685782f3

首先给出解决方案

1.https://github.com/nicklockwood/NullSafe

github上点赞过1k NullSafe是NSNull上的一个简单类别,对于任何无法识别的消息返回nil而不是抛出异常

或者

2自定义NSDictionary类拓展(原理:当我们给一个NSNull对象发送消息的话,可能会崩溃(null是有内存的),而发送给nil的话,是不会崩溃的)

-----有在网上看到其他博客是NSNull类型全部转换成@""空字符串的,但是我觉得nil更好些

#import <Foundation/Foundation.h>

@interface NSDictionary (AVHelper)
- (id)av_safeValueForKey:(NSString *)key;
- (NSDictionary *)av_safeValueArrayForKey:(NSString *)key;
- (NSDictionary *)av_safeValueMutableArrayForKey:(NSString *)key;
- (NSDictionary *)av_safeValueDictonaryForKey:(NSString *)key;
- (NSDictionary *)av_safeValueMutableDictionaryForKey:(NSString *)key;
- (NSDictionary *)av_safeValueDateForKey:(NSString *)key;
@end

#import "NSDictionary+AVHelper.h"

@implementation NSDictionary (AVHelper)

#pragma mark - public method

- (id)av_safeValueForKey:(NSString *)key {
    id value = [self valueForKey:key];
    if([value isKindOfClass:[NSNull class]]){
        value = nil;
    }
    return value;
}

- (NSDictionary *)av_safeValueArrayForKey:(NSString *)key {
    return [self av_safeValueForKey:key originalClass:[NSArray class]];
}

- (NSDictionary *)av_safeValueMutableArrayForKey:(NSString *)key {
    return [self av_safeValueForKey:key originalClass:[NSMutableArray class]];
}

- (NSDictionary *)av_safeValueDictonaryForKey:(NSString *)key {
    return [self av_safeValueForKey:key originalClass:[NSDictionary class]];
}

- (NSDictionary *)av_safeValueMutableDictionaryForKey:(NSString *)key {
    return [self av_safeValueForKey:key originalClass:[NSMutableDictionary class]];
}

- (NSDictionary *)av_safeValueDateForKey:(NSString *)key {
    return [self av_safeValueForKey:key originalClass:[NSDate class]];
}

#pragma mark - private method
- (id)av_safeValueForKey:(NSString *)key originalClass:(Class)aClass {
    id value = [self valueForKeyPath:key];
    if ([value isKindOfClass:[NSNull class]]) {
        value = nil;
    }
    
    if (value) {
        return value;
    }
    
    if (aClass == [NSString class]) {
        return @"";
    }
    
    if (aClass == [NSNumber class]) {
        return @0;
    }
    
    NSArray *array = @[@"NSArray",
                       @"NSMutaleArray",
                       @"NSDictionary",
                       @"NSMutableDictionary",
                       @"NSDate"];
    
    for (NSString *className in array) {
        Class bClass = NSClassFromString(className);
        if (aClass != bClass) {
            continue;
        }
        
        value = [[bClass alloc] init];
        break;
    }
    
    return value;
}

@end

如果有兴趣继续看

写了个小demo,问题产生原因一目了然

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSNull *pit = [NSNull null];
        NSDictionary *dic=  @{
                              @"debug":pit
                              };
        id value = dic[@"debug"];
        /*
         注销这行代码程序会崩溃
        */
//        if ([value isKindOfClass:[NSNull class]]) {
//            value = nil;
//        }
        
        NSString *str = value;
        if (str.length==0) {
            NSLog(@"发消息时不崩溃");
        }
        
        NSLog(@"%@",str);
    }
    return 0;
}
没有注销代码时
注销代码时
上一篇下一篇

猜你喜欢

热点阅读