nil:你到底是讓我有多么藍(lán)瘦香菇?

注明:圖中的兩個(gè)全為nil

前言


其實(shí)才短短工作了幾個(gè)月的時(shí)間,就有不少人問我關(guān)于nil的處理問題,因?yàn)閱柕娜撕芏?為了方便后來之人,(PS:騷棟你不要把自己說得那么高尚,你不就是為了圖省事嗎?以后有人問你這個(gè)問題,你好直接好甩博客給人家?you see see you !)咳咳,好了下面我就要說說我對(duì)nil的處理幾種方式.


nil 出現(xiàn)原因


其實(shí) nil大部分是出現(xiàn)在網(wǎng)絡(luò)請(qǐng)求這一部分,出現(xiàn)nil的情況主要是有兩種,一種是沒有網(wǎng)絡(luò)的情況下,仍然向服務(wù)器請(qǐng)求數(shù)據(jù),這樣請(qǐng)求下來的整體數(shù)據(jù)就為nil,另外一種就是由于后臺(tái)人員的不小心或者一些意外因素,導(dǎo)致請(qǐng)求下來的數(shù)據(jù)有一個(gè)nil的存在(不是全部數(shù)據(jù)昂),這時(shí)候如果使用你來nil賦值,程序雖然不會(huì)崩潰,但是一個(gè)空白值,不管如何都是我們不想要的結(jié)果.

下面我就對(duì)這兩種出現(xiàn)情況的處理逐一說明.


無網(wǎng)絡(luò),數(shù)據(jù)為nil的解決方案


這里我要說明一下,是無網(wǎng)絡(luò),而不是服務(wù)器未響應(yīng),如果是服務(wù)器無響應(yīng),那么給對(duì)應(yīng)的NSError對(duì)象賦值,這里無網(wǎng)絡(luò)的情況可不會(huì)給NSError對(duì)象賦值.
解決方案其實(shí)很簡(jiǎn)單,只要我們把加上一個(gè)if語(yǔ)句即可.這里我用AFNetworking做一下范例,(請(qǐng)求地址無效,純粹是為講解)

在加代碼保護(hù)之前,如下圖所示.其中responseObject為請(qǐng)求的網(wǎng)絡(luò)數(shù)據(jù),可能為空,如果是nil的話,直接進(jìn)行解析程序會(huì)直接崩潰的.

接下來,我們只需要做簡(jiǎn)單的一步就可以解決這個(gè)問題,一個(gè)判斷分支.如下所示.(是不是很簡(jiǎn)單呢?)


服務(wù)器數(shù)據(jù)問題,數(shù)據(jù)為nil的解決方案


有時(shí)候呢,在服務(wù)器端 數(shù)據(jù)可能本身就是為nil,但是服務(wù)器人員跟你說,沒有空值,大膽的用吧,然后哐當(dāng)?shù)囊宦?翻車了.

對(duì)于這種我們?cè)撊绾谓鉀Q呢?
這里我提供幾個(gè)方案.大家參考使用即可.(以NSString類型為例)


1.對(duì)NSString寫個(gè)延展(Category).

延展的.h和.m代碼如下所示.我們主要是在這個(gè)延展方法中判斷當(dāng)前的NSString對(duì)象是否nil,如果是那么對(duì)對(duì)象進(jìn)行相應(yīng)的空值操作,如果不是,直接返回.

#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

使用的時(shí)候,我們首先導(dǎo)入延展的頭文件#import "NSString+NilSafe.h",然后我們?nèi)缦率褂?

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

但是如果數(shù)據(jù)一多這種解決方案就不太方便了,我們不能每一個(gè)控制器都導(dǎo)入頭文件吧,還沒每一個(gè)地方都寫這么一堆代碼是吧,所以這種解決方案只是適合范圍較小的情況.


2.使用NullSafe.m

NullSafe這是一個(gè)歪果仁寫的一個(gè)Category,我們只要把NullSafe.m拖進(jìn)我們的工程即可.點(diǎn)擊下載NullSafe.然后我們就不需要做任何操作了,只要有空值nil,他就會(huì)自動(dòng)轉(zhuǎn)換.

但是NullSafe真的是我們想要的結(jié)果嗎?不不不,NullSafe雖然把空值轉(zhuǎn)換成不崩潰的數(shù)據(jù),但是你們看看轉(zhuǎn)換成了什么了."<null>"是不可以直接編輯的,也就說它并不能直接轉(zhuǎn)換成其他類型,然后你的頁(yè)面就是各種"<null>".

NullSafe綜合來說還是很方便的,但是卻不能解決一些小問題.


3.重寫數(shù)據(jù)模型model中的-(void)setValue:(id)value forKey:(NSString *)key方法

iOS中,我們都知道我們?cè)谧鼍W(wǎng)絡(luò)請(qǐng)求的時(shí)候呢,喜歡使用model來存儲(chǔ)數(shù)據(jù).那么我們經(jīng)常創(chuàng)建的model中寫容錯(cuò)處理方法-(void)setValue:(id)value forUndefinedKey:(NSString *)key,但是-(void)setValue:(id)value forKey:(NSString *)key方法,卻是不經(jīng)常寫的.但是我們今天要用到的是賦值方法.

通常呢,我們把網(wǎng)絡(luò)數(shù)據(jù)請(qǐng)求解析完,我們會(huì)把對(duì)應(yīng)的字典使用- (void)setValuesForKeysWithDictionary:這個(gè)方法直接賦值給我們的model如下圖所示.(因?yàn)檎?qǐng)求地址為無效值,所以不可能成功,只做參考)

我們都知道- (void)setValuesForKeysWithDictionary:這個(gè)使用字典賦值的方法其實(shí)是封裝的-(void)setValue:(id)value forKey:(NSString *)key這個(gè)方法的,所以我們需要在model中的重寫賦值方法

TestModel.h文件中的所有屬性

現(xiàn)在的需求是 如果數(shù)據(jù)為空,那么我們就會(huì)讓用戶看到"無"這個(gè)字.,假設(shè)現(xiàn)在TestModel(測(cè)試model)的name屬性可能為nil.這樣我們就需要在.m文件中的賦值方法做以下操作.直接判斷key是否為name并且value是否為nil,滿足條件那么就做出對(duì)應(yīng)的修改.

-(void)setValue:(id)value forKey:(NSString *)key{

    [super setValue:value forKey:key];
    
    if ([key isEqualToString:@"name"] &&value ==nil) {
        
        self.name = @"無";
        
    }
}

但是,使用上面的解決方法如果說屬性少還好說一點(diǎn),寫幾個(gè)if就是了,實(shí)際情況中一個(gè)model有可能含有十個(gè)或者十個(gè)以上的屬性,這時(shí)候難道我們要寫十個(gè)if嗎?為此,我想了個(gè)解決方案,那就是先對(duì)value進(jìn)行判斷,然后再調(diào)用父類方法,這樣,一個(gè)if就可以把含有空值的所有的屬性都做了判斷.具體實(shí)現(xiàn)如下.

-(void)setValue:(id)value forKey:(NSString *)key{

    if (value == nil) {
        value = @"無";
    }

    [super setValue:value forKey:key];
   
}

但是,這樣的解決方案也是有問題的,比如說我想name屬性為nil的時(shí)候,轉(zhuǎn)化為字符串"姓名無",address為nil的時(shí)候,轉(zhuǎn)化為"地址未填寫".這種情況就是解決不了的,如果解決,又會(huì)回到第一個(gè)方式了.

總結(jié):總體上來說,四種解決方法各有利弊,只要根據(jù)實(shí)際情況不同的選擇即可.


結(jié)束語(yǔ)


好了,大家終于知道在iOS中空值nil到底有讓人多么藍(lán)瘦香菇了吧,最后附上Demo傳送門.

--->NilSafeDemo傳送門??

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容