在上一篇文章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í)行,不然在else
中return
涡真。
對(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 case
和let
的組合闯捎。我們同樣會(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)雅的代碼哦。