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-闭包

相关推荐
mykj15515 小时前
英语单词APP解锁学习新方式,智能高效背单词
学习·英语单词app
知识分享小能手6 小时前
深度学习学习教程,从入门到精通,深度学习中的正则化 — 完整知识点与代码示例(7)
人工智能·深度学习·学习
CocoaKier7 小时前
苹果续费成功,几天后付费协议突然失效,导致线上苹果支付全部失败
ios·apple
~kiss~7 小时前
Agent 的 未来吗?String: An Agentic OS Where Every App Is a Markdown File
学习
HugoStudio_SWAN7 小时前
洛谷 B4450 / B3867 / B3923 智慧购物、储蓄与做题——从程序到生活
c++·学习·程序人生·算法·生活
UIU1149 小时前
scanf与cout的误区:探究其内部的机制
c++·学习·c#·scanf
zyf10441614 小时前
暑期实践日志 Day48:复盘大纲与知识点对照表,系统汇总整理成果
学习·计算机网络·剪辑·暑期实践·课题任务
m4Rk_15 小时前
【论文阅读】Agent 记忆机制(61):CFGM——用粗到细的记忆落地贯通经验采集、知识蒸馏与在线纠错
论文阅读·人工智能·学习·开源·github
边境悍匪15 小时前
蜗牛学苑 Java 智能体学习 Day33|AOP 面向切面编程、日志技术思维导图复盘
学习
我是你的开心果77815 小时前
ai全栈软件开发day21(第四阶段喽)
人工智能·学习