Optional Pattern
更新歷史:
- 2015.10.31新增case-let其他寫法
當(dāng)變量存在值有可能缺失的情況下使用可選類型,官方文檔如下定義:
- There is a value ,and it equals x,值存在且等于x.
- There isn't a value at all,值不存在!
本文今天不涉及基礎(chǔ)語(yǔ)法,更多有關(guān)可選類型的內(nèi)容,請(qǐng)看Why coding like this--自己創(chuàng)建一個(gè)可選類型一文。
Swift1.2和Swift2.0 解包方式
Swift1.2
早前我們都喜歡使用if-let或者??進(jìn)行可選類型進(jìn)行解包,形如:
//這是一個(gè)整數(shù)可選類型
let someOptional:Int? = 42 //你可以改成nil試試 會(huì)發(fā)現(xiàn)沒(méi)有輸出了
//以前的解包方式
if let x = someOptional{
print("someOptional value is \(x)")
}
var y = someOptional ?? 4
Swift2.0
而如今,Swift2.0又一次創(chuàng)新,新增如下兩種方式。不如先一睹風(fēng)采:
//1
//新增使用enumeration匹配 也就是枚舉匹配方式
if case .Some(let x) = someOptional{
print("someOptional value is \(x)") //如果為nil 情況 可不會(huì)輸出東西 因?yàn)槠ヅ涞氖荢ome!
}
//2
//新增使用可選模式匹配
if case let x? = someOptional{
print("someOptional value is \(x)") //不需要對(duì)x進(jìn)行解包之類的東東
}
可選類型是一個(gè)枚舉,存在case None 以及 case Some(T)兩種情況,其中T是包裹的值。
對(duì)于case .Some(let x) = someOptional這種匹配模式,右邊的someOptional是一個(gè)可選類型,完整定義是:let someOptional:Int? = 42,換種方式寫成case .Some(42)顯然兩者是匹配的,那么順?biāo)浦郯?code>x = 42嘍。倘若someOptional = nil了呢?依舊轉(zhuǎn)換成case .None,這時(shí)候左右兩邊是不匹配的! 有關(guān)更多匹配文章,請(qǐng)見(jiàn)swift.gg站點(diǎn)文章。
對(duì)于case let x? 其實(shí)和case .Some(let x)是一個(gè)道理。
兩種解包優(yōu)勢(shì)在哪里?
有人問(wèn)if-let解包 和 if case let x? 解包有什么區(qū)別?說(shuō)實(shí)話,博主目前也不清楚。希望有人告知,-。
這并不意味著if case let x?沒(méi)有存在的價(jià)值,例如
let arrayOptionalInts:[Int?] = [nil,1,2,3,nil,5] //數(shù)組的類型是Int? 可選類型嘍
//遍歷是用for-in
//swift 1.2寫法
for x in arrayOptionalInts{
if let y = x{
print("Found a \(y)")//把非 nil 值輸出來(lái)
}
}
//swift 2.0寫法
//把解包行為提前到for 語(yǔ)句中了
for case let number? in arrayOptionalInts{
print("Found a \(number)")
}
有對(duì)比才有發(fā)現(xiàn),確實(shí)這時(shí)候新語(yǔ)法更勝一籌。
拓展
下面我寫了一個(gè)小例子,以角色游戲?yàn)楸尘?,游戲中有玩家、NPC和怪物。如下聲明:
// 游戲角色 有玩家 NPC 怪獸
enum GameRole{
case Player(name:String)// 玩家要有名字
case NPC(name:String,faction:String)//名字 所屬陣營(yíng)
case Monster(name:String,element:Int)//怪物名字 屬性 水火金木土 對(duì)應(yīng)1-5
}
var roles = [
GameRole.Player(name: "玩家一"),
GameRole.Player(name: "玩家二"),
GameRole.Player(name: "玩家三"),
GameRole.Player(name: "玩家四"),
GameRole.NPC(name: "NPC1", faction: "光明"),
GameRole.NPC(name: "NPC2", faction: "黑暗"),
GameRole.NPC(name: "NPC3", faction: "精靈"),
GameRole.NPC(name: "NPC4", faction: "黑暗"),
GameRole.Monster(name: "怪物1", element: 1),
GameRole.Monster(name: "怪物2", element: 2),
GameRole.Monster(name: "怪物3", element: 4),
GameRole.Monster(name: "怪物4", element: 5),
]
// 早前使用方法
// 遍歷整個(gè)角色
for role in roles{
// 因?yàn)槭敲杜e 所以要switch來(lái)匹配
switch role{
case .NPC:
print("有 NPC 出沒(méi)")
default:
break
}
}
可以看到想要遍歷所有roles中的NPC 比如先用for-in循環(huán),隨后再用switch來(lái)進(jìn)行匹配找到NPC。代碼過(guò)于冗余,甚是不爽啊。好在Swift2.0中引入的case let解包方式,以下會(huì)讓你耳目一新:
for case .NPC in roles{
print("NPC找到")
}
倘若我還想要NPC中關(guān)聯(lián)的名字以及陣營(yíng)呢?
for case let .NPC(name,faction) in roles{
print("NPC找到 name:\(name) 陣營(yíng):\(faction)")
}
苛刻一點(diǎn) 我只想要黑暗陣營(yíng)的NPC!
for case let .NPC(name,faction) in roles where faction == "黑暗"{
print("NPC找到 name:\(name) 陣營(yíng):\(faction)")
}
恩.可能你還看不慣case-let這種寫法,或許你對(duì)其還是無(wú)感。但是我若是這么寫呢?
(2015.10.31更新)
for case .NPC(let name, let faction) in roles where faction == "黑暗"{
print("NPC找到 name:\(name) 陣營(yíng):\(faction)")
}
如此純正的枚舉匹配,為此你還有疑惑? 倘若需要自定義匹配模式,需要重載func ~=(pattern:value)這一方法。
倘若你覺(jué)得文章不錯(cuò),請(qǐng)關(guān)注我,點(diǎn)擊喜歡。另外推薦swift技術(shù)群:392436022。