IOS-闭包学习-Swift

介绍

闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数(Lambdas)比较相似。

闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕获过程中涉及到的所有内存操作。

形式

闭包有如下三种形式:

  • 全局函数是一个有名字但不会捕获任何值的闭包
  • 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
  • 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包

Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:

  • 利用上下文推断参数和返回值类型
  • 隐式返回单表达式闭包,即单表达式闭包可以省略 return 关键字
  • 参数名称缩写
  • 尾随闭包语法

示例

假如有这样一个数组,我们要对其进行字母逆序排序:

swift 复制代码
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

该例子对一个 String 类型的数组进行排序,因此排序闭包函数类型需为 (String, String) -> Bool。

提供排序闭包函数的一种方式是撰写一个符合其类型要求的普通函数,并将其作为 sorted(by:) 方法的参数传入:

swift 复制代码
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames 为 ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

语法

闭包表达式语法有如下的一般形式:

swift 复制代码
{ (parameters) -> return type in
    statements
}

闭包表达式参数 可以是 in-out 参数,但不能设定默认值。如果你命名了可变参数,也可以使用此可变参数。元组也可以作为参数和返回值。

下面的例子展示了之前 backward 函数对应的闭包表达式版本的代码:

swift 复制代码
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

需要注意的是内联闭包参数和返回值类型声明与 backward函数类型声明相同。在这两种方式中,都写成了 (s1: String, s2: String) -> Bool。然而在内联闭包表达式中,函数和返回值类型都写在大括号内,而不是大括号外。

闭包的函数体部分由关键字 in 引入。该关键字表示闭包的参数和返回值类型定义已经完成,闭包函数体即将开始。

由于这个闭包的函数体部分如此短,以至于可以将其改写成一行代码:

swift 复制代码
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )

根据上下文推断类型

因为排序闭包函数是作为 sorted(by:) 方法的参数传入的,Swift 可以推断其参数和返回值的类型。sorted(by:) 方法被一个字符串数组调用,因此其参数必须是 (String, String) -> Bool 类型的函数。这意味着 (String, String) 和 Bool 类型并不需要作为闭包表达式定义的一部分。因为所有的类型都可以被正确推断,返回箭头(->)和围绕在参数周围的括号也可以被省略:

swift 复制代码
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

单表达式闭包的隐式返回

如果闭包表达式只有一行,return 关键字都可以省略:

swift 复制代码
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

参数名称缩写

Swift 自动为内联闭包提供了参数名称缩写功能,你可以直接通过 0,1,$2 来顺序调用闭包的参数,以此类推,in 关键字也同样可以被省略。

swift 复制代码
reversedNames = names.sorted(by: { $0 > $1 } )

运算符方法

实际上还有一种更简短的方式来编写上面例子中的闭包表达式。Swift 的 String 类型定义了关于大于号(>)的字符串实现,其作为一个函数接受两个 String 类型的参数并返回 Bool 类型的值。而这正好与 sorted(by:) 方法的参数需要的函数类型相符合。因此,你可以简单地传递一个大于号,Swift 可以自动推断找到系统自带的那个字符串函数的实现:

swift 复制代码
reversedNames = names.sorted(by: >)

参考:SwiftGG-闭包

相关推荐
兔兔爱学习兔兔爱学习21 小时前
Spring Al学习7:ImageModel
java·学习·spring
江苏世纪龙科技1 天前
新能源汽车动力系统拆装与检测实训MR软件介绍-比亚迪秦EV标准版
学习
im_AMBER1 天前
数据结构 09 二叉树作业
数据结构·笔记·学习
00后程序员张1 天前
如何提高 IPA 安全性 多工具组合打造可复用的 iOS 加固与反编译防护体系(IPA 安全 iOS 加固 无源码混淆 Ipa Guard 实战)
android·安全·ios·小程序·uni-app·iphone·webview
wdfk_prog1 天前
[Linux]学习笔记系列 -- [kernel][time]hrtimer
linux·笔记·学习
四谎真好看1 天前
Java 黑马程序员学习笔记(进阶篇21)
java·开发语言·笔记·学习·学习笔记
立志成为大牛的小牛1 天前
数据结构——三十三、Dijkstra算法(王道408)
数据结构·笔记·学习·考研·算法·图论
何故染尘優1 天前
docker学习笔记,从入门开始!
笔记·学习·docker
D.....l1 天前
STM32学习(MCU控制)(WiFi and MQTT)
stm32·单片机·学习
摆烂积极分子1 天前
安卓开发学习10-中级控件
学习