美文网首页iOS 开发 @IT·互联网程序员
nil:你到底是让我有多么蓝瘦香菇?

nil:你到底是让我有多么蓝瘦香菇?

作者: 神经骚栋 | 来源:发表于2016-10-13 19:56 被阅读1102次
    注明:图中的两个全为nil

    前言


    其实才短短工作了几个月的时间,就有不少人问我关于nil的处理问题,因为问的人很多,为了方便后来之人,(PS:骚栋你不要把自己说得那么高尚,你不就是为了图省事吗?以后有人问你这个问题,你好直接好甩博客给人家?you see see you !)咳咳,好了下面我就要说说我对nil的处理几种方式.

    nil 出现原因


    其实 nil大部分是出现在网络请求这一部分,出现nil的情况主要是有两种,一种是没有网络的情况下,仍然向服务器请求数据,这样请求下来的整体数据就为nil,另外一种就是由于后台人员的不小心或者一些意外因素,导致请求下来的数据有一个nil的存在(不是全部数据昂),这时候如果使用你来nil赋值,程序虽然不会崩溃,但是一个空白值,不管如何都是我们不想要的结果.

    下面我就对这两种出现情况的处理逐一说明.

    无网络,数据为nil的解决方案


    这里我要说明一下,是无网络,而不是服务器未响应,如果是服务器无响应,那么给对应的NSError对象赋值,这里无网络的情况可不会给NSError对象赋值.
    解决方案其实很简单,只要我们把加上一个if语句即可.这里我用AFNetworking做一下范例,(请求地址无效,纯粹是为讲解)

    在加代码保护之前,如下图所示.其中responseObject为请求的网络数据,可能为空,如果是nil的话,直接进行解析程序会直接崩溃的.

    接下来,我们只需要做简单的一步就可以解决这个问题,一个判断分支.如下所示.(是不是很简单呢?)

    服务器数据问题,数据为nil的解决方案


    有时候呢,在服务器端 数据可能本身就是为nil,但是服务器人员跟你说,没有空值,大胆的用吧,然后哐当的一声,翻车了.

    对于这种我们该如何解决呢?
    这里我提供几个方案.大家参考使用即可.(以NSString类型为例)

    1.对NSString写个延展(Category).

    延展的.h和.m代码如下所示.我们主要是在这个延展方法中判断当前的NSString对象是否nil,如果是那么对对象进行相应的空值操作,如果不是,直接返回.

    #import <Foundation/Foundation.h>
    
    @interface NSString (NilSafe)
    
    +(NSString *)NilSafeWithString:(NSString *)string;
    
    @end
    
    
    #import "NSString+NilSafe.h"
    
    @implementation NSString (NilSafe)
    
    +(NSString* )NilSafeWithString:(NSString *)string{
    
        if (string == nil) {
            return [NSString stringWithFormat:@"无"];
        }else{
    
            return string;
        }
    
    }
    
    @end
    
    

    使用的时候,我们首先导入延展的头文件#import "NSString+NilSafe.h",然后我们如下使用.

        NSString *testString = nil;
        self.label.text = [NSString NilSafeWithString:testString];
    
    

    但是如果数据一多这种解决方案就不太方便了,我们不能每一个控制器都导入头文件吧,还没每一个地方都写这么一堆代码是吧,所以这种解决方案只是适合范围较小的情况.

    2.使用NullSafe.m

    NullSafe这是一个歪果仁写的一个Category,我们只要把NullSafe.m拖进我们的工程即可.点击下载NullSafe.然后我们就不需要做任何操作了,只要有空值nil,他就会自动转换.

    但是NullSafe真的是我们想要的结果吗?不不不,NullSafe虽然把空值转换成不崩溃的数据,但是你们看看转换成了什么了."<null>"是不可以直接编辑的,也就说它并不能直接转换成其他类型,然后你的页面就是各种"<null>".

    NullSafe综合来说还是很方便的,但是却不能解决一些小问题.

    3.重写数据模型model中的-(void)setValue:(id)value forKey:(NSString *)key方法

    iOS中,我们都知道我们在做网络请求的时候呢,喜欢使用model来存储数据.那么我们经常创建的model中写容错处理方法-(void)setValue:(id)value forUndefinedKey:(NSString *)key,但是-(void)setValue:(id)value forKey:(NSString *)key方法,却是不经常写的.但是我们今天要用到的是赋值方法.

    通常呢,我们把网络数据请求解析完,我们会把对应的字典使用- (void)setValuesForKeysWithDictionary:这个方法直接赋值给我们的model如下图所示.(因为请求地址为无效值,所以不可能成功,只做参考)

    我们都知道- (void)setValuesForKeysWithDictionary:这个使用字典赋值的方法其实是封装的-(void)setValue:(id)value forKey:(NSString *)key这个方法的,所以我们需要在model中的重写赋值方法

    TestModel.h文件中的所有属性

    现在的需求是 如果数据为空,那么我们就会让用户看到"无"这个字.,假设现在TestModel(测试model)的name属性可能为nil.这样我们就需要在.m文件中的赋值方法做以下操作.直接判断key是否为name并且value是否为nil,满足条件那么就做出对应的修改.

    -(void)setValue:(id)value forKey:(NSString *)key{
    
        [super setValue:value forKey:key];
        
        if ([key isEqualToString:@"name"] &&value ==nil) {
            
            self.name = @"无";
            
        }
    }
    

    但是,使用上面的解决方法如果说属性少还好说一点,写几个if就是了,实际情况中一个model有可能含有十个或者十个以上的属性,这时候难道我们要写十个if吗?为此,我想了个解决方案,那就是先对value进行判断,然后再调用父类方法,这样,一个if就可以把含有空值的所有的属性都做了判断.具体实现如下.

    -(void)setValue:(id)value forKey:(NSString *)key{
    
        if (value == nil) {
            value = @"无";
        }
    
        [super setValue:value forKey:key];
       
    }
    

    但是,这样的解决方案也是有问题的,比如说我想name属性为nil的时候,转化为字符串"姓名无",address为nil的时候,转化为"地址未填写".这种情况就是解决不了的,如果解决,又会回到第一个方式了.

    总结:总体上来说,四种解决方法各有利弊,只要根据实际情况不同的选择即可.

    结束语


    好了,大家终于知道在iOS中空值nil到底有让人多么蓝瘦香菇了吧,最后附上Demo传送门.

    --->NilSafeDemo传送门🚪

    相关文章

      网友评论

        本文标题:nil:你到底是让我有多么蓝瘦香菇?

        本文链接:https://www.haomeiwen.com/subject/fknwyttx.html