zoukankan      html  css  js  c++  java
  • iOS请求服务器数据去空NSNull

    我们在处理数据库接口的过程中,如果数据中出现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
     

    相关链接:

    删除字典中的null

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

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

  • 相关阅读:
    代理工具
    python-requests简单使用
    Charles使用 请求转发【map remote】 rewrite-body替换 rewrite-modify query param
    charles监控 移动端HTTPS请求
    unittest执行测试用例过程
    JVM工具命令
    JAVA开发小技巧
    命名神器(妈妈再也不用担心我瞎命名了)
    CookieUtil、EncryptUtil(各种加密算法)、HttpUtil
    常见Maven命令
  • 原文地址:https://www.cnblogs.com/On1Key/p/5446367.html
Copyright © 2011-2022 走看看