近期在使用Moya框架时用到这几个关键词,在此对 if case,guard case,for case
做了以下复习测试与总结。
if case let
语句
case let x = y
模式允许你检查y
是否能匹配x
。
而if case let x = y { … }
严格等同于switch y { case let x: … }
:当你只想与一条 case 匹配时,这种更紧凑的语法尤其有用。有多个 case 时更适合使用switch
。
- 假设我们要用以下的枚举数组判断是否是男性然后打印,正常如下方法使用:
// 人分为:男性,女性,中性
// 男人拥有:姓名,年龄,游戏机数量
// 女人拥有:姓名,年龄,化妆品数量
// 中性拥有:姓名
enum PersonKind {
case Man(name: String, age: Int,playerNumber:Int)
case Woman(name: String, age: Int, HuaZhuangPinNumber: Int)
case UnknowPerson(name: String)
}
let pk1 = PersonKind.Man(name: "周杰伦", age: 30, playerNumber: 2000)
// let pk2 : PersonKind = PersonKind.Woman(name: "张柏芝", age: 35, HuaZhuangPinNumber: 1000)
// let pk3 = PersonKind.UnknowPerson(name: "泰国人之张三")
switch pk1 {
case let PersonKind.Man(name, age, playerNumber):
print(name,age,playerNumber)
case let PersonKind.Woman(name, age, HuaZhuangPinNumber):
print(name,age,HuaZhuangPinNumber)
case let PersonKind.UnknowPerson(name):
print(name)
}
- 如果用了if case 可以这样写来替换上述写法,方便简洁:
if case let PersonKind.Man(name, age, playerNumber) = pk1 {
print(name,age,playerNumber)
}
if case let where
if case let where
,比上面多一个关键词where相当于多一个条件,比如判断男性,并且如果游戏机的数量大于100才进行打印,现在由于swift版本问题,where用逗号,
代替,在后面进行条件拼接即可,如果你写了where,Xcode也会自动帮你纠错。
if case let PersonKind.Man(name, age, playerNumber) = pk1, playerNumber > 100 {
print(name,age,playerNumber)
}
guard case let
当然,
guard case let
类似于if case let
,你可以使用guard case let
和guard case let … where …
来确保匹配一个模式或一个条件,而当无法匹配模式或满足条件时就退出。
还拿上述案例说明:
let pk1 = PersonKind.Man(name: "周杰伦", age: 30, playerNumber: 2000)
guard case let PersonKind.Man(name, age, playerNumber) = pk1, playerNumber > 3000 else{
print("男性,游戏机数量大于3000这两个条件肯定有一个不成立")
return
}
for case let
将
for
和case
组合在一起也能让你有条件地遍历一个集合对象。使用for case …
语义上类似于for
循环,而且将它整个循环体封装在了if case
的结构之中:它只会遍历、处理那些模式匹配了的元素。
- 举例如下,遍历数组找到数组中的中性人并打印:
let pk1 = PersonKind.Man(name: "周杰伦", age: 30, playerNumber: 2000)
let pk2 : PersonKind = PersonKind.Woman(name: "张柏芝", age: 35, HuaZhuangPinNumber: 1000)
let pk3 = PersonKind.UnknowPerson(name: "泰国人之张三")
let array = [pk3,pk1,pk2,pk3,pk3]
for case let PersonKind.UnknowPerson(name) in array{
print(name)
}
/*
打印结果:
泰国人之张三
泰国人之张三
泰国人之张三
*/
for case let ... where
同理,相当于多一个条件,where关键词放在集合的后面
- 举例如下,找到集合中的泰国人并且名叫
泰国人之张三
的人:
let pk1 = PersonKind.Man(name: "周杰伦", age: 30, playerNumber: 2000)
let pk2 : PersonKind = PersonKind.Woman(name: "张柏芝", age: 35, HuaZhuangPinNumber: 1000)
let pk3 = PersonKind.UnknowPerson(name: "泰国人之张三")
let pk4 = PersonKind.UnknowPerson(name: "泰国人之王五")
let array = [pk3,pk1,pk2,pk3,pk3,pk4]
for case let PersonKind.UnknowPerson(name) in array where name == "泰国人之张三"{
print(name)
}
/*
打印结果,不会打印王五这个人:
泰国人之张三
泰国人之张三
泰国人之张三
*/
注意:使用 for … where 而不带 case 模式匹配依然是符合 Swift 语法规则的。比如你这样写也是 OK 的:
for m in array where m.name == "泰国人之张三" { … }
这里没有使用模式匹配(没有 case 或 ~=),因此有点超出了本系列的主题范围,但是这种写法是完全有效的,而且这种构造也非常有用—特别是避免了将一个巨大的判断逻辑 if 结构(或是一个 guard … else { continue })封装在 for 的循环体内。
举例综合使用
- 找出集合中额外物品大于0的种类的名字
extension PersonKind{
var kind : String?{
switch self {
case .Man(_, _,_):
return "男性种类"
case .Woman(_,_,_):
return "女性种类"
default:
return "中性种类"
}
}
// 额外物品数量
var extraSomething : Int{
switch self {
case let .Man(_,_, playerNumber):
return playerNumber
case let .Woman(_,_, HuaZhuangPinNumber):
return HuaZhuangPinNumber
default:
return 0
}
}
}
let pk1 = PersonKind.Man(name: "周杰伦", age: 30, playerNumber: 2000)
let pk2 : PersonKind = PersonKind.Woman(name: "张柏芝", age: 35, HuaZhuangPinNumber: 1000)
let pk3 = PersonKind.UnknowPerson(name: "泰国人之张三")
let pk4 = PersonKind.UnknowPerson(name: "泰国人之王五")
let array = [pk3,pk1,pk2,pk3,pk3,pk4]
for case let (akind,bextra) in array.map({ ($0.kind, $0.extraSomething)})
where bextra > 0{
print(akind!,bextra)
}
/*
打印结果:
男性种类 2000
女性种类 1000
*/
数组array通过map函数映射为一个个的包括kind,extraSomething两个计算属性元素的元组集合,根据bextra > 0条件筛选出最终的结果。
参考博客
http://swift.gg/2016/06/06/pattern-matching-4/
http://www.hangge.com/blog/cache/detail_1807.html