点赞评论,希望能在你的帮助下越来越好
作者:@iOS成长指北,本文首发于公众号 iOS成长指北,欢迎各位前往指正
如有转载需求请联系我,记住一定要联系哦!!!
这是我参与更文挑战的第3天,活动详情查看:更文挑战
笔者在 Day13 – Swift 基础总结,1 中简述了 Swift 中 Switch 的用法。随着学习的过程,今天我们探讨一下在 Swift 中的模式匹配的用法,主要着力于 Switch 中的实现。
通配符模式
通配符模式由一个下划线(_)构成,用于匹配并忽略任何值,当你想忽略被匹配的值时可以使用该模式。
当我们处理具有关联值的枚举或者是元祖时,当我们想忽略某些匹配值时,使用这种模式
//枚举
enum Response {
case error(Int, String)
case success
}
let httpResponse = Response.error(300, "Network Error")
switch httpResponse {
case let .error(_, status):
print("HTTP Error: \(status)")
case .success:
print("HTTP Request was successful")
}
//元祖
switch (15, "example", 3.14) {
case (_, _, let pi):
print ("pi: \(pi)")
}
复制代码
一个不常见的示例是利用这种模式来进行可选项解包,可以通过附加 ?
来匹配可选项,使其成为_?
:
let p: String? = ""
switch p {
case _?:
print("p = ", p as Any)
case nil:
print("no words")
}
复制代码
更多关于 Swift 中的可选,可以查看笔者之前的 Day12 – 可选
标识符模式
标识符模式可以匹配任何值,并将匹配的一个变量或者常量绑定起来。
对于确定值的匹配,使用 Switch 而不是 if...else
代码更加的易读:
let name = "Harry"
switch name {
case "Harry":
print("哈利")
case "iOS":
print("成长指北")
default:
print("哈利波特")
}
复制代码
值绑定模式
值绑定模式把匹配到的值绑定给一个变量或者常量。
我们可以利用值绑定模式与其他模式进行匹配,例如,当我们实现一个实现用户登录功能的方法时,我们可以这么做
func usernameAndPassword()
-> (username: String, password: String)? {
//获取账户/密码,这里处理一些关于账户密码的校验
}
func usernameAndPassword()
-> (username: String, password: String)? {
//获取账户/密码,这里处理一些关于账户密码的校验
return (username: "iOS成长指北", password: "123123")
}
switch usernameAndPassword() {
case let (username, _)? where username == "iOS成长指北":
attention()
default:
like()
}
func attention() {
//关注
}
func like() {
//点赞
}
复制代码
你可以为特定的登录账户或密码做特定的事情。
元组模式
元组模式是由都好分隔的,具有零个或多个模式的列表,并由一对圆括号括起来。元组模式匹配到响应的元组类型值。
对多个条件的数据,我们可以利用元祖来匹配我们需要的条件:
let age = 23
let job: String? = "Operator"
let payload: Any = NSDictionary()
switch (age, job, payload) {
case (let age, _?, _ as NSDictionary):
print(age)
default: ()
}
复制代码
题外话:
最新新学到的一个关于利用元祖交换两个数据的方法
func swapTwoInTuple(_ x: inout Int, _ y: inout Int ) { (y, x) = (x, y) } var x = 10, y = 20 swapTwoInTuple(&x, &y) 复制代码
枚举用例模式
枚举用例模式匹配现有的某个枚举类型的某个用例。这应该是 Switch 中最常见的匹配模式了。对于 Switch 中关于枚举用例的匹配情况,这里主要关注的是关于枚举用例的关联值,同元组模式一样,我们可以可以对关联值进行多种条件判断。
enum Response {
case error(Int, String)
case success
}
let httpResponse = Response.error(300, "Network Error")
switch httpResponse {
case let .error(errorCode, status) where errorCode >= 300 && errorCode < 399 :
print("HTTP Error: \(status)")
case let .error(errorCode, status) where errorCode >= 400 && errorCode < 499 :
print("HTTP Error: \(status)")
case let .error(errorCode, status) where errorCode >= 500 && errorCode < 599 :
print("HTTP Error: \(status)")
case .success:
print("HTTP Request was successful")
default:()
}
复制代码
类型转换模式
有两种类型转换模式, is 模式
和 as 模式
, is 模式
只出现在 Switch 语句中用例(case)中。
is 模式
和 as 模式
-
is 模式
仅当一个值的类型在运行时和is 模式
右边的指定类型一致,或者是其子类的情况下,才会匹配这个值。is 模式
和is 运算符
有相似表现,它们都可进行类型转换,但是is 模式
忽略返回的类型。所以is 模式
无法使用值绑定 -
as 模式
仅当一个值得类型在运行时和as 模式
右边指定类型一致或者是其子类的情况下,才会匹配这个值,如果匹配成功,被匹配的值得类型被转换成as 模式
右边指定的类型返回
下面这个简单的例子说明了其中的区别
let num: Any = 5
switch num {
case is Int:
print (a + 1)
case let n as Double:
print (n + 1)
default: ()
}
复制代码
表达式模式
表达模式非常强大。它将 Switch 的值与实现 〜=
运算符的表达式进行匹配。此运算符有默认实现,例如区间、数组,在之前的学习中我们介绍了关于区间的匹配:
let wavelength = 620
switch wavelength {
case 380..<450:
print("Purple!")
case 450..<495:
print("Blue!")
default:
print("Not in visible spectrum")
}
复制代码
关于数组的匹配也是一个很好的例子
let myArray = [1, 2, 4, 3]
switch myArray {
case [..., 0, 0, 0]:
//以 3 个 0 结尾
case [4, ...]:
//以 4 开头
case [_, 2, _, 3]:
//第二个第四个是 2,3
case [_, _, 8]:
//第三个是 8
default: ()
}
复制代码
出来本身支持 〜=
运算符的类来说,对于自定义类来说,我们可以通过自定义 〜=
运算符来进行响应的匹配。实现 ~=
的函数原型如下,其中 PatternType
和 PredicateType
可以替换为你想要的任何类型:
func ~=(pattern: PatternType, predicate: PredicateType) -> Bool
复制代码
我们尝试一下下面的例子
struct Person {
var money: Int
}
func ~=(pattern: Range<Int>, predicate: Person) -> Bool {
return pattern.contains(predicate.money)
}
var reader: Person = Person(money: 1000)
switch reader {
case 0..<1000:
print("我")
case 1000..<5000:
print("点赞的")
case 5000..<10000:
print("分享的")
default:
print("关注的")
}
复制代码
更多关于运算符重载可以看看笔者之前写的 深入理解 Swift Operators
switch or if ?
在控制流中或者是进行条件判断时。我们应该如何选择,是使用 switch
还是使用 if
?
-
对于枚举类型的匹配,自然毋庸置疑的是使用
switch
了。因为 Swift 要求它的switch
语句是详尽的。在不适用default
的情况下,用switch
可以使 代码更具完整性和确保不会遗漏。一般如果只有两种类型的话,除非是有其他操作逻辑的话,用
if
会比使用switch
更好 -
当您使用 switch 检查一个值是否有多个可能的结果时,该值将仅读取一次,而使用 if 进行判断是则会被读取多次。当使用函数调用时,这变得尤为重要,因为其中一些调用速度可能很慢。
虽然进行函数调用时,我们一般都是先获取到值,在进行语句判断
-
switch
支持 元组、区间、值绑定还有where
,并且支持模式匹配,在处理复杂条件时一般建议你使用switch
。
如果你有任何问题,请直接评论,如果文章有任何不对的地方,请随意表达。如果你愿意,可以通过分享这篇文章来让更多的人发现它。
感谢你阅读本文! ?