Optional Pattern
更新历史:
- 2015.10.31新增case-let其他写法
当变量存在值有可能缺失的情况下使用可选类型,官方文档如下定义:
- There is a value ,and it equals x,值存在且等于x.
- There isn't a value at all,值不存在!
本文今天不涉及基础语法,更多有关可选类型的内容,请看Why coding like this--自己创建一个可选类型一文。
Swift1.2和Swift2.0 解包方式
Swift1.2
早前我们都喜欢使用if-let
或者??
进行可选类型进行解包,形如:
//这是一个整数可选类型
let someOptional:Int? = 42 //你可以改成nil试试 会发现没有输出了
//以前的解包方式
if let x = someOptional{
print("someOptional value is \(x)")
}
var y = someOptional ?? 4
Swift2.0
而如今,Swift2.0
又一次创新,新增如下两种方式。不如先一睹风采:
//1
//新增使用enumeration匹配 也就是枚举匹配方式
if case .Some(let x) = someOptional{
print("someOptional value is \(x)") //如果为nil 情况 可不会输出东西 因为匹配的是Some!
}
//2
//新增使用可选模式匹配
if case let x? = someOptional{
print("someOptional value is \(x)") //不需要对x进行解包之类的东东
}
可选类型是一个枚举,存在case None
以及 case Some(T)
两种情况,其中T
是包裹的值。
对于case .Some(let x) = someOptional
这种匹配模式,右边的someOptional
是一个可选类型,完整定义是:let someOptional:Int? = 42
,换种方式写成case .Some(42)
显然两者是匹配的,那么顺水推舟般x = 42
喽。倘若someOptional = nil
了呢?依旧转换成case .None
,这时候左右两边是不匹配的! 有关更多匹配文章,请见swift.gg站点文章。
对于case let x?
其实和case .Some(let x)
是一个道理。
两种解包优势在哪里?
有人问if-let
解包 和 if case let x?
解包有什么区别?说实话,博主目前也不清楚。希望有人告知,-。
这并不意味着if case let x?
没有存在的价值,例如
let arrayOptionalInts:[Int?] = [nil,1,2,3,nil,5] //数组的类型是Int? 可选类型喽
//遍历是用for-in
//swift 1.2写法
for x in arrayOptionalInts{
if let y = x{
print("Found a \(y)")//把非 nil 值输出来
}
}
//swift 2.0写法
//把解包行为提前到for 语句中了
for case let number? in arrayOptionalInts{
print("Found a \(number)")
}
有对比才有发现,确实这时候新语法更胜一筹。
拓展
下面我写了一个小例子,以角色游戏为背景,游戏中有玩家、NPC和怪物。如下声明:
// 游戏角色 有玩家 NPC 怪兽
enum GameRole{
case Player(name:String)// 玩家要有名字
case NPC(name:String,faction:String)//名字 所属阵营
case Monster(name:String,element:Int)//怪物名字 属性 水火金木土 对应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),
]
// 早前使用方法
// 遍历整个角色
for role in roles{
// 因为是枚举 所以要switch来匹配
switch role{
case .NPC:
print("有 NPC 出没")
default:
break
}
}
可以看到想要遍历所有roles中的NPC 比如先用for-in
循环,随后再用switch来进行匹配找到NPC。代码过于冗余,甚是不爽啊。好在Swift2.0中引入的case let
解包方式,以下会让你耳目一新:
for case .NPC in roles{
print("NPC找到")
}
倘若我还想要NPC中关联的名字以及阵营呢?
for case let .NPC(name,faction) in roles{
print("NPC找到 name:\(name) 阵营:\(faction)")
}
苛刻一点 我只想要黑暗阵营的NPC!
for case let .NPC(name,faction) in roles where faction == "黑暗"{
print("NPC找到 name:\(name) 阵营:\(faction)")
}
恩.可能你还看不惯case-let
这种写法,或许你对其还是无感。但是我若是这么写呢?
(2015.10.31更新)
for case .NPC(let name, let faction) in roles where faction == "黑暗"{
print("NPC找到 name:\(name) 阵营:\(faction)")
}
如此纯正的枚举匹配,为此你还有疑惑? 倘若需要自定义匹配模式,需要重载func ~=(pattern:value)
这一方法。
倘若你觉得文章不错,请关注我,点击喜欢。另外推荐swift技术群:392436022。