深入讲解Swift中的模式匹配

模式匹配

模式匹配是 Swift 中非常常见的一种编程模式,使用模式匹配,可以帮助我们写出简明、清晰以及易读的代码,使我们的代码变得简洁而强大。

条件判断中的模式匹配

条件判断是我们使用最普遍的流程控制,在 Swift 中,只能接受 Bool 类型的值作为条件体;除了直接判断 Bool 值之外,我们还能使用使用条件语句进行可选绑定,这在我们开发中是非常常用的方式。

匹配枚举值

在 Swift 中,创建的枚举类型默认是不可比较的(没有实现Comparable协议),这就意味着我们不能直接使用==操作符来判断两个枚举值是否相等,这种情况下,需要使用模式匹配:

创建一个枚举类型:

enum Result {
 case success
 case failure
}

初始化一个枚举值:

let result = Result.success

使用模式匹配来判断创建的枚举值的值:

if case .success = result {
 print("Value of result is success.")
}

可选绑定

创建一个可选值:

let optionalInt: Int? = 1

使用可选绑定的方式进行解包:

if let val = optionalInt {
 print("The value of optionalInt is (val)")
}
func handleGuard() {
 guard let val = optionalInt else {
 return
 }
 print("The value of optionalInt is (val)")
}
handleGuard()

可选绑定的另外一种模式,这也是可选绑定中最基础的模式:

if case .some(let val) = optionalInt {
 print("The value of optionalInt is (val)")
}

还可以简化为:

if case let val? = optionalInt {
 print("The value of optionalInt is (val)")
}

循环中的模式匹配

问题来了,if let 模式的可选绑定,只能实现一个可选值的绑定,如果我们需要匹配一个数组里边的可选值怎么办呢?这时候我们就不能使用 if let 的形式了,需要使用到 if case let 的形式

创建一个包含可选值的数组:

let values: [Int?] = [1, nil, 3, nil, 5, nil, 7, nil, 9, nil]

进行遍历:

for val in values {
 print("Value in values is (String(describing: val))")
}

或者:

var valuesIterator = values.makeIterator()
while let val = valuesIterator.next() {
 print("Value in values is (String(describing: val))")
}

我们得到了所有的值与可选值,如果我们需要过滤可选值,我们可以这样做:

for val in values.compactMap({ $0 }) {
 print("Value in values is (val)")
}

这样做,增加了时间复杂度,需要进行两次遍历才能将数据过滤出来。我们可以使用模式匹配的方式来这样做:

for case let val? in values {
 print("Value in values is (val)")
}

或者:

valuesIterator = values.makeIterator()
while let val = valuesIterator.next(), val != nil {
 print("Value in values is (String(describing: val))")
}

这样就可以将 nil 值给过滤了,是不是很简单?还可以使用 for case 匹配枚举值数组:

let results: [Result] = [.success, .failure]
for case .success in results {
 print("Values in results contains success.")
 break
}

对于复杂的枚举类型:

enum NetResource {
 case http(resource: String)
 case ftp(resource: String)
}

let nets: [NetResource] = [.http(resource: "https://www.baidu.com"), .http(resource: "https://www.apple.cn"), .ftp(resource: ftp://192.0.0.1)]

过滤 http 的值:

for case .http(let resource) in nets {
 print("HTTP resource (resource)")
}

for 循环使用 where 从句

除此之外,我们还可以在 for 循环后边跟上一个 where 从句来进行模式匹配:

for notNilValue in values where notNilValue != nil {
 print("Not nil value: (String(describing: notNilValue!))")
}

查询一个数组里边所有能被3整除的数:

let rangeValues = Array(0...999)
for threeDivideValue in rangeValues where threeDivideValue % 3 == 0 {
 print("Three devide value: (threeDivideValue)")
}

查询所有含有3的数:

for containsThree in rangeValues where String(containsThree).contains("3") {
 print("Value contains three: (containsThree)")
}

Switch 中的模式匹配

Switch 中的模式匹配也很常用,在 Switch 中合理地使用模式匹配可以为我们带来很多好处,可以使我们的代码更简洁,同时可以减少代码量和增加开发效率。

区间匹配

let value = 188

switch value {
case 0..<50:
 print("The value is in range [0, 50)")
case 50..<100:
 print("The value is in range [50, 100)")
case 100..<150:
 print("The value is in range [100, 150)")
case 150..<200:
 print("The value is in range [150, 200)")
case 200...:
 print("The value is in range [200, ")
default: break
}

// The value is in range [150, 200)

匹配元组类型

创建一个元组类型:

let tuples: (Int, String) = (httpCode: 404, status: "Not Found.")

进行匹配:

switch tuples {
case (400..., let status):
 print("The http code is 40x, http status is (status)")
default: break
}

创建一个点:

let somePoint = (1, 1)

进行匹配:

switch somePoint {
case (0, 0):
 print("(somePoint) is at the origin")
case (_, 0):
 print("(somePoint) is on the x-axis")
case (0, _):
 print("(somePoint) is on the y-axis")
case (-2...2, -2...2):
 print("(somePoint) is inside the box")
default:
 print("(somePoint) is outside of the box")
}

如上,我们在匹配的时候可以使用下划线 _ 对值进行忽略:

switch tuples {
case (404, _):
 print("The http code is 404 not found.")
default: break
}

在 switch case 中使用 where 从句

在 case 中使用 where 从句可以使我们的模式匹配看起来更加精简,使匹配的模式更加紧凑:

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
 print("((x), (y)) is on the line x == y")
case let (x, y) where x == -y:
 print("((x), (y)) is on the line x == -y")
case let (x, y):
 print("((x), (y)) is just some arbitrary point")
}

总结

Swift 中模式匹配的种类

模式匹配可以说是 Swift 中非常强大的一种编程模式,使用良好的模式匹配,可以帮助我们写出简介、优雅的代码,Swift 中的模式匹配包括以下种类:

  • 条件判断:if, guard
  • 可选绑定:if let, guard let, while let ...
  • 循环体:for, while, repeat while
  • switch
  • do catch

什么时候使用 where 从句?

我们可以在前文的例子中看到,在很多进行模式匹配的地方还使用了 where 从句,where 从句的作用就相当于在模式匹配的基础上在加上条件限制,使用 where 从句等价于:

for notNilValue in values {
 if notNilValue != nil {
  print("Not nil value: (String(describing: notNilValue!))")
 }
}

可以看出,使用 where 从句可以使我们的代码更加简洁和易读,什么时候使用 where ? 或者说在哪里可以使用 where ? Swift 文档中并没有对 where 的详细使用进行介绍,但是在实践中发现,where 可以使用在以下地方:

  • for 循环语句
  • switch 分支

而对于 if, guard 与 while ,我们不能在其后面添加 where 从句,因为他们本身可以进行多个条件的组合. where 从句还有一个用法就是对泛型类型进行类型约束,这在泛型的章节中会有介绍.

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 深入解析Swift代理模式

    配置如下: Xcode 8.2 Swift 3.0 在iOS开发中,无论是 Objective-C 还是 Swift ,Delegate 有着具足轻重的位置,如TabelViewDelegate 与 TableViewDataSource. Swift 中的代理模式 和 Objective-C 除了语法外,几乎一样. Objective-C 代理模式 在介绍 Swift 代理模式前,先来看回顾一下 Objective-C 中的代理模式如何实现 Objective-C 中用代理实现反向传值: 委托

  • 通过示例分析Swift单例模式

    三种Swift实现单例模式的方法:全局变量,内部变量,dispatch_once方式 1. 全局变量 private let _singleton = Singleton() class Singleton: NSObject { class var sharedInstance: Singleton { get { return _singleton } } } 2. 内部变量 class Singleton { class var sharedInstance: Singleton { ge

  • Swift开发中switch语句值绑定模式

    Switch简介 Switch作为选择结构中必不可少的语句也被加入到了Swift中,只要有过编程经验的人对Switch语句都不会感到陌生,但苹果对Switch进行了大大的增强,使其拥有其他语言中没有的特性. // switch语句值绑定模式 let point = (100, 10) switch point { // 遇到有匹配的就不会在执行下一个了 这样子也可以啊case let (x, y) case (let x, let y): print("\(x): \(y)") //

  • swift where与匹配模式的实例详解

    swift where与匹配模式的实例详解 前言: 在众多 Swift 提供给 Objective-C 程序员使用的新特性中,有个特性把自己伪装成一个无聊的老头,但是却在如何优雅的解决"鞭尸金字塔"的问题上有着巨大的潜力.很显然我所说的这个特性就是 switch 语句, 对于很多 Objective-C 程序员来说,除了用在 Duff's Device 上比较有趣之外,switch 语句非常笨拙,与多个 if 语句相比,它几乎没有任何优势. 1.基本使用 Swift中switch语句c

  • Swift中switch语句区间和元组模式匹配

    废话不多说了,下面一段代码给大家介绍了switch语句区间和元组模式匹配,具体内容如下所示: // switch 的广义匹配 let x = 1000 // 也就是说并没有像C语言那样 要求 switch 后面的是整数常量 switch x { // case后面可以跟区间啦 case 1...9: print("个位数") case 10...99: print("十位数") case 100...999: print("百位数") case

  • 深入理解Swift中单例模式的替换及Swift 3.0单例模式的实现

    前言 除了 MVC.MVVM 之外,单例模式可以说是 iOS 开发中另一常见的设计模式.无论是 UIKit 或是一些流行的三方库,我们都能看到单例的身影.而我们开发者本身也会潜意识地将这些类库中的代码当作最佳实践并将其带入日常工作中,哪怕很多人都知道单例存在一些明显的缺陷. 针对单例的缺陷,本文将介绍一些替换或改造单例模式的方法来提升代码质量. 单例的优点 除了上面提到的模仿最佳实践之外,单例的流行肯定也有内在的原因和理由.例如:单例对象保证了只有一个实例的存在,这样有利于我们协调系统整体的行为

  • 在Swift中使用Cocoa的现有设计模式介绍

    使用 Cocoa 现有的一些设计模式,是帮助开发者开发一款拥有合理设计思路.稳定的性能.良好的可扩展性应用的有效方法之一.这些模式都依赖于在 Objective-C 中定义的类.因为 Swift 与 Objective-C 的互用性,所以你依然可以在 Swift 代码中使用这些设计模式.在一些情况下,你甚至可以使用 Swift 语言的特性扩展或简化这些 Cocoa 设计模式,使这些设计模式更强大.更易于使用. 委托(Delegation) 在 Swift 和 Objective-C 中,委托通常

  • IOS Swift3 四种单例模式详解及实例

    Swift3 单例模式 常见的有这么几种方法 第一种简单到爆的 final class Single: NSObject { static let shared = Single() private override init() {} } final关键字的作用是这个类或方法不希望被继承和重写 第二种 public extension DispatchQueue { private static var onceToken = [String]() public class func once

  • 深入讲解Swift中的模式匹配

    模式匹配 模式匹配是 Swift 中非常常见的一种编程模式,使用模式匹配,可以帮助我们写出简明.清晰以及易读的代码,使我们的代码变得简洁而强大. 条件判断中的模式匹配 条件判断是我们使用最普遍的流程控制,在 Swift 中,只能接受 Bool 类型的值作为条件体:除了直接判断 Bool 值之外,我们还能使用使用条件语句进行可选绑定,这在我们开发中是非常常用的方式. 匹配枚举值 在 Swift 中,创建的枚举类型默认是不可比较的(没有实现Comparable协议),这就意味着我们不能直接使用==操

  • 实例讲解Swift中引用类型的ARC自动引用计数

    一.引言 ARC(自动引用计数)是Objective-C和Swift中用于解决内存管理问题的方案.在学习Objective-C编程时经常会学习到一个关于ARC的例子:在一个公用的图书馆中,每次进入一人就将卡插入,走的时候将自己的卡拔出拿走.图书馆系统会判定只要有卡插入,就将图书馆的灯打开,当所有卡都被取走后,将图书馆的灯关掉.这个例子对应于Objective-C中的对象声明周期管理十分贴切.每当一个对象增加一个引用时,其引用计数会加1,当一个引用被取消时,对象的引用计数减1,当引用计数减为0时,

  • 详细讲解Swift中的类型占位符

    Swift 的类型推断能力从一开始就是语言的核心部分,它极大地减少了我们在声明有默认值的变量和属性时手动指定类型的工作.例如,表达式var number = 7不需要包含任何类型注释,因为编译器能够推断出值7是一个Int,我们的number变量应该被相应的类型化. 作为 Xcode 13.3 的一部分而一起发布的 Swift 5.6,通过引入 "类型占位符(type placeholders) "的概念,继续扩展这些类型推理能力,这在处理集合和其他通用类型时非常有用. 例如,假设我们想

  • 举例讲解Swift编程中switch...case语句的用法

    Switch作为选择结构中必不可少的语句也被加入到了Swift中,只要有过编程经验的人对Switch语句都不会感到陌生,但苹果对Switch进行了大大的增强,使其拥有其他语言中没有的特性.使用Switch语句很简单: var i = 0 switch i { case 0: "0" //被输出 case 1: "1" default: "2" } 在这个最简单的Switch语句中,与其他语言很不同的一点是:不用显式的加上break.Swift的S

  • Swift中static和class关键字的深入讲解

    前言 Swift中表示 "类型范围作用域" 这一概念有两个不同的关键字,它们分别是static和class.这两个关键字确实都表达了这个意思,但是在其他一些语言,包括Objective-C中,我们并不会特别地区分类变量/类方法和静态变量/静态函数.但是在Swift中,这两个关键字却是不能用混的. static和class 作用:这两个关键字都是用来说明被修饰的属性或者方法是类型(class/struct/enum)的,而不是类型实例的. static 适用的场景(class/struc

  • 深入理解Swift中的变量与常量

    前言 最近在学习Swift这门新语言,对于熟练掌握OC编程的iOS开发者来说其实很容易上手,但Swift的确在语法和编程习惯上改变了很多,对于从未了解OC语言而从Swift开始学习iOS开发的新手来说可能上手有一定难度,下面我将这段时间的学习成果结合在网上搜索的知识做一个简单的汇总,希望可以帮助到正在学习Swift的小伙伴们. 变量和常量的定义 Swift开发文档中是这样定义变量和常量的:常量和变量把名字和一个特定类型的值关联起来.常量的值一旦设置好便不能再被更改,然而变量可以在将来被设置为不同

  • Swift中闭包实战案例详解

    前言 无论苹果的官方文档还是由官方文档衍生出来的一些文章和书籍都比较重视基础语法知识的讲解,对于实战中的应用提及的都很少,所以当我们想使用"闭包"解决一些问题的时候,会忽然出现看着一堆理论知识却不知从何下手的尴尬感,这就是理论和时实战的区别了. 本文不赘述Swift闭包的的基本语法了,百度或者Google下有很多资料.如题所示本文着重讲述Swift闭包的一些实战案例,有需要的小伙伴可以参考下,经验丰富的大神也请指教. 关于如何理解闭包 学习闭包的第一个难点就是理解闭包,可能很多人用了很

  • 在Swift中如何使用正则表达式详解

    前言 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念.正则表通常被用来检索.替换那些符合某个模式(规则)的文本. 正则表达式(Regular expression, regex)允许我们在几秒钟内在成千上万文档间进行复杂检索与替换,自从诞生50多年来它依旧广泛使用. Swift虽然是一个新出的语言,但却不提供专门的处理正则的语法和类.所以我们只能使用古老的NSRegularExpression类进行

  • Swift中通知中心(NotificationCenter)的使用示例

    前言 本文主要介绍了关于Swift通知中心(NotificationCenter)使用的相关内容,NotificationCenter是Swift中一个调度消息通知的类,采用单例模式设计,实现传值.回调等作用. 通知的作用还是挺强大的,对于两个不相关的控制器之间,要进行信息的传递,使用通知是个不错的选择,下面话不多说了,来一起看看详细的使用方法吧. 1.添加通知 /// 通知名 let notificationName = "XMNotification" /// 自定义通知 Noti

随机推荐