ios解决有关null闪退及json解析数据中null的问题

今天往NSUserdefault中存数组。程序crash了。 给我报错是

Attempt to set a non-property-list object....


意思就是存入了自定义类型的对象。或者无法识别的对象。


我首先想到了是数组的问题。 检查代码 没有用模型。

再用iskindofclass[nsarray class]检查  是数组没问题


后来检查数据发现数组元素中的字典  有个key对应的value 是null


所以存入nsuserdefault时 导致crash了。


解决办法:

ios中json解析出现的null问题

问题现象

但是几个项目下来一直遇到一个坑爹的问题,程序在获取某些数据之后莫名崩溃。其实很早就发现了原因:由于服务器的数据库中有些字段为空,然后以Json形式返回给客户端时就会出现这样的数据:

"somevalue":null

通过JsonKit 这个第三方库解析出来的数据就成了

somevalue = "<null>";

这个数据类型不是nil 也不是 String。 解析成对象之后,如果直接向这个对象发送消息(eg:length,count 等等)就会直接崩溃。提示错误为:

 -[NSNull length]unrecognized selector sent to instance 0x388a4a70

解决方法

其实一直没有找到完美的解决办法,坑了我很久。

1、最开始的解决方法就是为了应付当前遇到的崩溃,看看哪个字段可能为空,那么就对该字段使用前进行判断,通过崩溃时的错误提示可以看出,这样的字段解析成的对象是 NSNull 类型的,所以可以直接判断是不是此类型:

 if (![isKindOfClass:[NSNull class]]){xxxxxxx;}

因为字段实在太多,就找一个补一个。

2、后来想彻底解决这问题,就打算从数据源下手,其实应该可以用正则表达式匹配这个null ,然后进行替换,奈何正则是我的硬伤啊。于是就相出了一个山寨方法:字符串匹配。在获取到服务器返回的Json时,返回结果时string对象,于是就先替换 null 为 为空字符””,然后再解析。

json = [jsonStr  stringByReplacingOccurrencesOfString:@":null" withString:@":\"\""];

这个方法本来很奏效,但是我这里的服务器返回极不简洁,各种垃圾数据(不吐槽这了)。。。反正这样会导致json无法解析了。

3、最后没有办法,只能在解析的时候下手,把是NSNull 类型的值替换成nil。 一般就写个tool方法,然后解析时调用。但是嫌太麻烦,就想弄写个宏,通过搜索惊奇的发现宏也是可以有返回值的,结果如下:

#define VerifyValue(value)\
({id tmp;\
if ([value isKindOfClass:[NSNull class]])\
tmp = nil;\
else\
tmp = value;\
tmp;\
})\

宏里的最后一句语句便是返回值。然后在解析数据时调用宏:

contact.contactPhone = VerifyValue(contactDic[@"send_ContactPhone"]);

4、如果你使用AFNetwork 这个库做网络请求的话,可以用以下代码,自动帮你去掉这个讨厌的空值

如果你使用的类是AFHTTPSessionManager那么有:

AFHTTPSessionManager *manager = [[AFHTTPSessionManager alloc]initWithBaseURL:url sessionConfiguration:config];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
[serializer setRemovesKeysWithNullValues:YES];
[manager setResponseSerializer:serializer];

如果用的是

AFHTTPRequestOperation:

AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request];
AFJSONResponseSerializer *serializer = [AFJSONResponseSerializer serializer];
serializer.removesKeysWithNullValues = YES;
op.responseSerializer = serializer;

5、终极方案
终于找到了一劳永逸的方案,牛逼的老外写了一个Category,叫做NullSafe ,在运行时操作,把这个讨厌的空值置为nil,而nil是安全的,可以向nil对象发送任何message而不会奔溃。这个category使用起来非常方便,只要加入到了工程中就可以了,你其他的什么都不用做,对,就是这么简单。详细的请去Github上查看;
https://github.com/nicklockwood/NullSafe

亲测5导入后没好用。请使用成功的童鞋指点一二。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值