我们在处理数据库接口的过程中,如果数据中出现null,我们是没法处理的。我在使用NSUserDaults
保存后,出现崩溃。
null产生原因
null是后台在处理数据的时候,如果没有设置value
值,数据库默认填充的值。
解决办法
- 数据库做处理
- 本地做删除null处理
本地做删除null处理
如果是数据库做处理的话,可以在数据库中,将未设置的value
填充为" "即可。
如果是本地处理的话,我个人是通过添加类别来达到效果的。
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
- ( NSDictionary *)deleteNull{ NSMutableDictionary *mutableDic = [[ NSMutableDictionary alloc] init]; for ( NSString *keyStr in self .allKeys) { if ([[ self objectForKey:keyStr] isEqual:[ NSNull null]]) { [mutableDic setObject:@ "" forKey:keyStr]; } else { [mutableDic setObject:[ self objectForKey:keyStr] forKey:keyStr]; } } return mutableDic; } |
-------------------------------------------------------------------------------------------------
在iOS开发过程中经常需要与服务器进行数据通讯,Json就是一种常用的高效简洁的数据格式。
问题现象
但是几个项目下来一直遇到一个坑爹的问题,程序在获取某些数据之后莫名崩溃。其实很早就发现了原因:由于服务器的数据库中有些字段为空,然后以Json形式返回给客户端时就会出现这样的数据:
1
|
"somevalue" :null |
通过JsonKit 这个第三方库解析出来的数据就成了
1
|
somevalue = "<null>" ; |
这个数据类型不是nil 也不是 String。 解析成对象之后,如果直接向这个对象发送消息(eg:length,count 等等)就会直接崩溃。提示错误为:
1
|
-[ NSNull length]: unrecognized selector sent to instance 0x388a4a70 |
解决方法
其实一直没有找到完美的解决办法,坑了我很久。
1、最开始的解决方法就是为了应付当前遇到的崩溃,看看哪个字段可能为空,那么就对该字段使用前进行判断,通过崩溃时的错误提示可以看出,这样的字段解析成的对象是 NSNull 类型的,所以可以直接判断是不是此类型:
1
|
if (![isKindOfClass:[ NSNull class ]]){xxxxxxx;} |
因为字段实在太多,就找一个补一个。
2、后来想彻底解决这问题,就打算从数据源下手,其实应该可以用正则表达式匹配这个null ,然后进行替换,奈何正则是我的硬伤啊。于是就相出了一个山寨方法:字符串匹配。在获取到服务器返回的Json时,返回结果时string对象,于是就先替换 null 为 为空字符””,然后再解析。
1
|
json = [jsonStr stringByReplacingOccurrencesOfString:@ ":null" withString:@ ":""" ]; |
这个方法本来很奏效,但是我这里的服务器返回极不简洁,各种垃圾数据(不吐槽这了)。。。反正这样会导致json无法解析了。
3、最后没有办法,只能在解析的时候下手,把是NSNull 类型的值替换成nil。 一般就写个tool方法,然后解析时调用。但是嫌太麻烦,就想弄写个宏,通过搜索惊奇的发现宏也是可以有返回值的,结果如下:
1
2
3
4
5
6
7
8
|
#define VerifyValue(value) ({ id tmp; if ([value isKindOfClass:[ NSNull class ]]) tmp = nil ; else
tmp = value; tmp; }) |
宏里的最后一句语句便是返回值。然后在解析数据时调用宏:
1
|
contact.contactPhone = VerifyValue(contactDic[@ "send_ContactPhone" ]); |
4、如果你使用AFNetwork 这个库做网络请求的话,可以用以下代码,自动帮你去掉这个讨厌的空值
1
|
self .removesKeysWithNullValues = YES ; |
5、终极方案
终于找到了一劳永逸的方案,牛逼的老外写了一个Category,叫做NullSafe ,在运行时操作,把这个讨厌的空值置为nil,而nil是安全的,可以向nil对象发送任何message而不会奔溃。这个category使用起来非常方便,只要加入到了工程中就可以了,你其他的什么都不用做,对,就是这么简单。详细的请去Github上查看;
https://github.com/nicklockwood/NullSafe
---------------------------------------------------------------------
解决NSArray和NSDictionary中含有null时 writeToFile 失败的问题
@implementation NSArray(Plist) -(BOOL)writeToPlistFile:(NSString*)filename{ NSData * data = [NSKeyedArchiver archivedDataWithRootObject:self]; NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentsDirectory = [paths objectAtIndex:0]; NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; BOOL didWriteSuccessfull = [data writeToFile:path atomically:YES]; return didWriteSuccessfull; } +(NSArray*)readFromPlistFile:(NSString*)filename{ NSArray * paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString * documentsDirectory = [paths objectAtIndex:0]; NSString * path = [documentsDirectory stringByAppendingPathComponent:filename]; NSData * data = [NSData dataWithContentsOfFile:path]; return [NSKeyedUnarchiver unarchiveObjectWithData:data]; } @end //needs to be set for implementation
相关链接: