Swift中一些常見的關(guān)鍵字二(if let,guard let, if case, if case let)

在上一篇文章Swift中一些常見的關(guān)鍵字一(inout,defer,throw等)簡單的介紹了幾個(gè)關(guān)鍵字。本文續(xù)寫。

guard

guard關(guān)鍵字和常見的if關(guān)鍵字是一對(duì)兄弟般的關(guān)系呢诬。兩者的目的是同樣的 -- 進(jìn)行條件判別;只是在使用上有所不同胖缤。
我們很熟悉if-else尚镰,它表示條件成立則執(zhí)行if中的內(nèi)容,不然執(zhí)行else語句中的內(nèi)容哪廓。而guard-else則表示狗唉,如果guard成立則繼續(xù)往下執(zhí)行,不然在elsereturn涡真。
對(duì)比一段代碼加深了解:

// if   -  else
let a = 100
if a % 20 == 0{ 
    if a % 5 == 0{
          print(a / 5)      
    }
}
return
///  這是一個(gè)雙重判斷語句分俯,需要在兩個(gè)`if`條件都通過的情況下,才能執(zhí)行到我們真正的邏輯代碼哆料。

很顯然缸剪,這種嵌套寫法很不友好,可讀性也很差东亦,可以進(jìn)行改進(jìn):

let a = 100
if a % 20 == 0 && a % 5 == 0{ 
    print(a / 5)      
}
return

盡管這樣這樣已經(jīng)很簡潔了杏节,但是當(dāng)我們的條件越來越多的時(shí)候, if 判斷的代碼將變的更長更復(fù)雜典阵,這種方式的可讀性其實(shí)也不好奋渔。不僅如此,多條件的綜合判斷將使得代碼更加混亂壮啊,可讀性也隨之降低嫉鲸,這并不十分可取。
那繼續(xù)改進(jìn)一下:

let a = 100
if a % 20 != 0 { return }
if a % 5 != 0{ return }
print(a / 5) 

這里我們思維轉(zhuǎn)換了一下歹啼,取他們的相反的邏輯進(jìn)行處理充坑。理解起來的話减江,不再是如果......就......,而是除非......那么
顯然這種方式的可讀性是最好的捻爷,我個(gè)人推薦這種方式。 但是份企,這種方式并非完美也榄,因?yàn)槭褂?code>if實(shí)現(xiàn)除非語法,我們總要謹(jǐn)記在括號(hào)內(nèi)帶上return字段司志,如果漏掉甜紫,代碼邏輯就會(huì)出現(xiàn)問題,而編譯器卻不會(huì)報(bào)錯(cuò) --- 這增加了代碼bug的概率骂远。Swift提供了一種安全的方式囚霸,書寫除非......語句 --- guard-else
同樣激才,上面的代碼使用guard-else來實(shí)現(xiàn)如下:

let a = 100
guard  a % 20  == 0 else{  return  }
guard  a % 5  == 0 else{  return  }
print(a / 5) 

Swift規(guī)定拓型,guard - else必須同時(shí)出現(xiàn),而且瘸恼,else中劣挫,必須進(jìn)行return
這就保證了我們不會(huì)漏掉return东帅,同時(shí)压固,guard條件本身也是正相關(guān):如果條件成立則執(zhí)行下一步。這符合我們的思維習(xí)慣靠闭,相比之下帐我, if ! 則需要我們對(duì)條件進(jìn)行一個(gè)非轉(zhuǎn)換愧膀,和我們的思維習(xí)慣不合拦键。這里體現(xiàn)了guard - else的優(yōu)勢。
當(dāng)然扇调,guard - else不能取代if - else矿咕。如果是兩個(gè)選擇判斷語句中,我們還是使用if -- else語法更為合理狼钮。比如:

//這種不存在結(jié)束的條件判斷碳柱,并不適合使用guard關(guān)鍵字。
let a = 100 
if a > 80{
   print(a-80)
}esle{
   print(80-a)
}

總結(jié)熬芜, guard - else除非 - 則.. - 不然 - 結(jié)束的語法中莲镣,使用最為合適。

if let

if let 關(guān)鍵字是一個(gè)組合關(guān)鍵字涎拉。我們主要使用它解決Optional對(duì)象解包時(shí)產(chǎn)生空對(duì)象的處理瑞侮。
Swift中的圆,有著嚴(yán)格類型安全要求,如果一個(gè)對(duì)象可能為nil的時(shí)候半火,我們需要對(duì)這個(gè)對(duì)象用?進(jìn)行修飾,就像下面這個(gè)屬性:

var prop: String? = nil      //初始化為一個(gè)空對(duì)象

如果我們需要使用這個(gè)prop的時(shí)候越妈,由于這是一個(gè)封包(Optional)對(duì)象,也叫可選對(duì)象钮糖,如果直接調(diào)用梅掠,需要帶上修飾符號(hào)店归,就像這樣:

self.prop阎抒! = "test"      

prop后的!會(huì)被強(qiáng)制攜帶,不然會(huì)報(bào)錯(cuò)消痛。這是因?yàn)榍胰x值操作是一個(gè)確定類型的動(dòng)作,所以需要使用 ! 對(duì) 秩伞?修飾的可選對(duì)象進(jìn)行解包逞带。這種寫法其實(shí)欠妥的,因?yàn)槌砬福?dāng)prop是一個(gè)nil的時(shí)候掰担,上面這個(gè)語句將會(huì)報(bào)錯(cuò),原因:為nil賦值是不允許的怒炸。
當(dāng)然带饱,我們可以對(duì)這個(gè)對(duì)象進(jìn)行判斷,如果不為空才執(zhí)行賦值操作阅羹。如:

if self.prop != nil{  self.prop勺疼! = "test"   } 
或者
guard self.prop != nil else{ return }
self.prop! = "test"

而實(shí)際上,在Swift中捏鱼,提供一種專門的方式用于解包時(shí)的操作执庐,那就是if let 關(guān)鍵字。依然是上面的例子导梆,使用if let 書寫的話如下:

if let aProp = self.prop{
    aProp =  "test"
    ...其他更多的操作
}

這個(gè)例子是對(duì)顯式的封包屬性進(jìn)行操作轨淌,除此之外,if let 還可以用于強(qiáng)制的類型轉(zhuǎn)換看尼。
正常情況下递鹉,我們在Swift 中是不能進(jìn)行類型轉(zhuǎn)換的,如果強(qiáng)轉(zhuǎn)藏斩,導(dǎo)致Crash的概率很高 ---- 就算是開發(fā)者躏结,也同樣不能保證自己的對(duì)象類型是不是真的是要轉(zhuǎn)化的類型。if let 用于可像下面這樣安全的進(jìn)行強(qiáng)制轉(zhuǎn)換:

if let  typeAObj = typeBObj as? typeA{
     // 如果能夠轉(zhuǎn)換成功狰域,那么typeAObj就是強(qiáng)轉(zhuǎn)后的對(duì)象
     ....
}else {
     // 轉(zhuǎn)化失敗媳拴,這里一般不會(huì)做處理
}

if case

在學(xué)習(xí) if case之前黄橘,我們先想想,那些地方使用到了case 這個(gè)關(guān)鍵字屈溉,毫無疑問塞关,絕大多數(shù)使用case的時(shí)候,是在 switch語法中子巾。
Swift中的if case主要用于模式匹配描孟。跟switch很類似,但它本身有特別的使用場景砰左,區(qū)別switch在于,switch用于對(duì)所有的對(duì)象可能值進(jìn)行判斷场航,而if case之需要對(duì)關(guān)注的可能值進(jìn)行判斷缠导。老規(guī)矩,還是代碼上看看溉痢。
假設(shè)我有一個(gè)枚舉變量CarBrand,汽車品牌僻造。它的結(jié)構(gòu)如下:

enum CarBrand{
   case  BMW
   case  AUDI
   case  BENZ
}

如果使用switch進(jìn)變量匹配,并按照不同的車的品牌輸出對(duì)應(yīng)的中文名字(這種需求當(dāng)然可以通過添加屬性值的方式更簡便的解決孩饼,但這里我們只討論if case的使用髓削,暫時(shí)不關(guān)注其他的方式。)镀娶。我們可能是這樣做的:

let myBrand = CarBrand.BMW
switch myBrand{
    case .BMW: do{   print("寶馬")  }
    case .AUDI: do{   print("奧迪")  }
    case .BENZ: do{   print("奔馳")  }
}


實(shí)際上立膛,我們可能僅僅是想找出BMW的品牌而已,但是我卻需要寫一部分跟這個(gè)品牌無關(guān)的代碼梯码。我們可以進(jìn)行一點(diǎn)簡化:

switch myBrand{
    case .BMW: do{   print("寶馬")  }
    default: ()  // do  nothing
}

可能覺得這個(gè)方式還是過于繁瑣宝泵,有什么辦法可以像if那樣對(duì)枚舉值判斷嗎?
if case應(yīng)該能幫到你:

let myBrand = CarBrand.BMW
if case .BMW = myBrand{
   print("寶馬")
}

這樣不就舒服多了轩娶,不僅沒有冗余的代碼儿奶,還有具備了更好的可讀性。

if case let

if case let它實(shí)際上不是一個(gè)完整的關(guān)鍵字鳄抒,它 if caselet的組合闯捎。我們同樣會(huì)在對(duì)枚舉類型進(jìn)行模式匹配的時(shí)候用到它,不過這個(gè)情況稍微復(fù)雜一點(diǎn)许溅。
假設(shè)我的CarBrand枚舉想要集合更多的東西瓤鼻,比如它的中文名字和生產(chǎn)地。我們可以這樣定義這個(gè)枚舉:

enum CarBrand{
    case  BMW(name:String,Production:String)
    case  AUDI(name:String,Production:String)
    case  BENZ(name:String,Production:String)
}

現(xiàn)在我定一個(gè)枚舉變量:

let myCar = CarBrand.BMW(name: "寶馬",Production: "德國")

如果我想輸出myCar的關(guān)聯(lián)屬性闹司,直接使用點(diǎn)語法什么的都顯然是不行的娱仔。我們可在枚舉中自定義一些輸出關(guān)聯(lián)屬性的方法,但是這個(gè)做法比較繁瑣游桩,并且破壞了枚舉結(jié)構(gòu)牲迫。
比較簡單的是可以使用switch:

switch myCar {
  case let CarBrand.BMW(name,Production):
    print("This car named \(name)耐朴,from\(Production)")
  default: () // 不做任何處理
}

這樣確實(shí)可以的。同樣我們覺得這樣還是過于繁瑣了盹憎。
使用if case let

 let myBrand = CarBrand.BMW(name: "寶馬",Production: "德國")
 if case let CarBrand.BMW(name, Production) = myBrand{
     print("\(name),\(Production)")
}

是不是更加簡潔呢筛峭。當(dāng)然,if case let 還可一配合where從句寫出更加優(yōu)雅的代碼哦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末陪每,一起剝皮案震驚了整個(gè)濱河市影晓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌檩禾,老刑警劉巖挂签,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異盼产,居然都是意外死亡饵婆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門戏售,熙熙樓的掌柜王于貴愁眉苦臉地迎上來侨核,“玉大人,你說我怎么就攤上這事灌灾〈暌耄” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵锋喜,是天一觀的道長些己。 經(jīng)常有香客問我,道長跑芳,這世上最難降的妖魔是什么轴总? 我笑而不...
    開封第一講書人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮博个,結(jié)果婚禮上怀樟,老公的妹妹穿的比我還像新娘。我一直安慰自己盆佣,他們只是感情好往堡,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著共耍,像睡著了一般虑灰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上痹兜,一...
    開封第一講書人閱讀 49,144評(píng)論 1 285
  • 那天穆咐,我揣著相機(jī)與錄音,去河邊找鬼。 笑死对湃,一個(gè)胖子當(dāng)著我的面吹牛崖叫,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播拍柒,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼心傀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拆讯?” 一聲冷哼從身側(cè)響起脂男,我...
    開封第一講書人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤宰翅,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后爽室,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡肮之,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年卜录,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艰毒。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖丑瞧,靈堂內(nèi)的尸體忽然破棺而出柑土,到底是詐尸還是另有隱情绊汹,我是刑警寧澤稽屏,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站西乖,受9級(jí)特大地震影響狐榔,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜获雕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一薄腻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧届案,春花似錦庵楷、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽咐蚯。三九已至,卻和暖如春蜓斧,著一層夾襖步出監(jiān)牢的瞬間仓蛆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來泰國打工挎春, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留看疙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓直奋,卻偏偏與公主長得像能庆,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子脚线,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345