我们在处理数据库接口的过程中,如果数据中出现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:];
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:];
NSString * path = [documentsDirectory stringByAppendingPathComponent:filename];
NSData * data = [NSData dataWithContentsOfFile:path];
return [NSKeyedUnarchiver unarchiveObjectWithData:data];
} @end //needs to be set for implementation
 

相关链接:

删除字典中的null

关于Json中null的问题以及宏的返回值

解决NSArray和NSDictionary中含有null时 writeToFile 失败的问题

iOS请求服务器数据去空NSNull的更多相关文章

  1. 关于纯xmlhttprequest请求服务器数据

    今天我们的web技术已经相当的完善, 各种前端框架如jquery或者再深一点的工具APIcloud 的使用极大的方便了我们的开发工作. 今天我要分享一个纯javascript的方式来解决请求服务器数据 ...

  2. Ajax在jQuery中的应用(加载异步数据、请求服务器数据)

    加载异步数据 jQuery中的load()方法 load(url,[data],[callback]) url:被加载的页面地址 [data]:可选项表示发送到服务器的数据,其格式为 key/valu ...

  3. IOS 请求服务器的方式

    IOS 中请求服务器的方式主要有Get 和Post . Get :[1]向服务器发索取数据的一种请求; [2]获取信息,而不是修改信息,类似数据库查询功能一样,数据不会被修改;请求的参数会跟在url后 ...

  4. app请求服务器数据方法1-HttpUrlConnection

    1. 实例化URL对象 首先第一步实例化一个URL对象,传入参数为请求的数据的网址. URL url = new URL("http://www.imooc.com/api/teacher? ...

  5. APP请求服务器数据-HttpUrlConnection

    1. 实例化URL对象 首先第一步实例化一个URL对象,传入参数为请求的数据的网址. URL url = new URL("http://www.imooc.com/api/teacher? ...

  6. java ajax长连接请求服务器数据

    Servlet 3.0笔记之异步请求Comet推送长轮询(long polling)篇 Comet另一种形式为长轮询(long polling),客户端会与服务器建立一个持久的连接,直到服务器端有数据 ...

  7. 使用ajax()方法加载服务器数据

    使用ajax()方法加载服务器数据 使用ajax()方法是最底层.功能最强大的请求服务器数据的方法,它不仅可以获取服务器返回的数据,还能向服务器发送请求并传递数值,它的调用格式如下: jQuery.a ...

  8. iOS服务器数据请求"汉字编码"问题

    下面记录一下数据请求问题: 1.不知道大家有木有遇到过,当数据请求的URL带有汉字的时候,请求数据肯定会报404错误,也就是参数或者是接口URL错误<虽然说404,500等错误一般都是服务器问题 ...

  9. iOS - NetRequest 网络数据请求

    1.网络请求 1.1 网络通讯三要素 1.IP 地址(主机名): 网络中设备的唯一标示.不易记忆,可以用主机名(域名). 1) IP V4: 0~255.0~255.0~255.0~255 ,共有 2 ...

随机推荐

  1. CRM 2013 系统设置新功能一:界面自动保存 及 SDK 中 Xrm.Page.data.entity.save

    CRM 2013 界面会自动保存了..在系统设置中默认“是”,如果不需要可以调整. CRM实体记录在新建时会有出现“保存”按钮,非新建状态下,没有“保存”按钮只有“新建”按钮,系统将会自动为你保存最后 ...

  2. [ html canvas createImageData 创建万花筒效果 ] canvas绘图属性 createImageData 属性讲解 及创建万花筒效果

    <!DOCTYPE html> <html lang='zh-cn'> <head> <title>Insert you title</title ...

  3. Searching External Data in SharePoint 2010 Using Business Connectivity Services

    from:http://blogs.msdn.com/b/ericwhite/archive/2010/04/28/searching-external-data-in-sharepoint-2010 ...

  4. JSP--JavaBean

    JSP 最强有力的一个方面就是能够使用 JavaBean 组件. 按照 Sun 公司的定义, JavaBean是一个可重复使用的软件组件.实际上 JavaBean 是一种 Java 类,通过封装属性和 ...

  5. pycharm安装与实践

    PyCharm简介 PyCharm是一种Python IDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试.语法高亮.Project管理.代码跳转.智能提示.自动完成. ...

  6. Swift控制流

    本文简单的介绍swift一些基本语法的使用,在本文中不会做更深的剖析,只提及一些语法的简单的使用,快速学会编写swift程序.高手请绕路走嘿嘿 常量与变量: swift中定义所有的变量使用var,定义 ...

  7. 建立JDBC的环境配置和相关下载(Mac)

    首先已经安装好XMAPP和Workbench. 1.打开MySQL,然后打开Workbench: 然后我们需要下载MySQL的JDBC驱动. 1.进入MySQL官网:http://dev.mysql. ...

  8. 在XcodeGhost事件之后,获取更纯净的Xcode的方法。

    正值Xcode 7正式版本的更新,IOS界就冒出了个甚至可以说成涉及国家安全的大事也不为过的事件: 也可以点击网址链接看总结的更完整的文章:众多知名 APP 都中毒了,XCodeGhost 病毒事件汇 ...

  9. Eclipse 导入项目后启动报异常:java.lang.UnsatisfiedLinkError: Native Library *.dll already loaded in another classloade 解决方法

    tomcat 服务器的配置信息如下:

  10. .NET 反射的使用

    1.根据类名获取类实例 string className = "Company.BigProgram.BLL.TestClass"; Type type = Type.GetTyp ...