在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;
}
网友评论