swift - Swift 中的闭包:它们是什么?他们是如何工作的?
问题描述
我正在阅读一本关于 Swift 基础知识的书,而关于闭包的部分对我来说毫无意义。
这是他们提供的示例:
要对数组进行排序以使小数排在大数之前,您可以提供一个描述如何进行排序的闭包,如下所示:
var numbers = [2,1,56,32,120,13]
// Sort so that small numbers go before large numbers
var numbersSorted = numbers.sort({
(n1: Int, n2: Int) -> Bool in return n2 > n1
})
// = [1, 2, 13, 32, 56, 120]
我不明白在这种情况下关闭的目的是什么——numbers.sort()
即使没有关闭也不会返回相同的值?另外,我不确定闭包在这里逐步执行的实际操作。
更广泛地说,我不能从这个例子中确定你何时可以在 Swift 中使用闭包。从精神上讲,它们似乎接近于减少功能,但我不确定你什么时候会使用它们。
编辑:这个代码示例在我正在使用的 Swift 游乐场(v. 12.0)中不起作用也无济于事。它抱怨调用sort
是Missing argument label 'by:' in call
. 也许有一个更好的闭包例子。
解决方案
用非常简单的术语来说,闭包是一个可以传递的函数。
关于使用排序,您可以选择对对象的不同属性进行排序,因此您可能希望创建自己的自定义排序函数/闭包。
sort
注意 Swift和sorted
Swift之间是有区别的。sort
改变原始数组,sorted
创建数组的副本。所以在你的例子numbersSorted
中不会有一个值,sorted
如果你希望它有一个值,你应该使用它。
let numbers = [2, 5, 3, 2, 1, 0, -8, 12]
let numbersSorted = numbers.sorted { first, second -> Bool in
return first < second
}
print(numbers) // [2, 5, 3, 2, 1, 0, -8, 12]
print(numbersSorted) // [-8, 0, 1, 2, 2, 3, 5, 12]
但是我不需要像那样编写上面的代码。我可以将闭包换成函数。
let numbers = [2, 5, 3, 2, 1, 0, -8, 12]
func ascending(first: Int, second: Int) -> Bool {
first < second
}
let numbersSorted = numbers.sorted(by: ascending)
print(numbers) // [2, 5, 3, 2, 1, 0, -8, 12]
print(numbersSorted) // [-8, 0, 1, 2, 2, 3, 5, 12]
请注意,该函数ascending
与我们之前使用的闭包具有相同的签名。
或者,我可以将闭包编写为变量,然后可以传递
let numbers = [2, 5, 3, 2, 1, 0, -8, 12]
let ascending = { (first: Int, second: Int) in
return first < second
}
let numbersSorted = numbers.sorted(by: ascending)
print(numbers) // [2, 5, 3, 2, 1, 0, -8, 12]
print(numbersSorted) // [-8, 0, 1, 2, 2, 3, 5, 12]
最重要的是函数和闭包的签名匹配。这样他们就可以互换了。
我个人更喜欢选择第二个选项,因为它使代码更具可读性并且看起来更干净。
当涉及到闭包时,您必须应对另一个术语,那就是@escaping
. 这意味着什么?
@escaping
闭包的寿命比它传递给的函数长。基本上是说这个代码应该在函数被调用后执行。
这在网络呼叫时很常见,因为它们可能需要一段时间才能完成。该函数将已执行但您尚未收到响应,一旦返回响应,它就会执行完成块(我们的闭包),我们可以看到更新。
这里有一些你可以跟进的好文章
https://learnappmaking.com/closures-swift-how-to/
https://www.hackingwithswift.com/example-code/language/what-is-a-closure
https://www.swiftbysundell.com/basics/closures/
https://www.hackingwithswift.com/example-code/language/what-is-an-escaping-closure
推荐阅读
- python - dask map_partitions(pd.cut, bins) 实际上会在整个数据帧上运行吗?
- javascript - 如何从数据库中显示html标签
- listview - setOnItemClickListener 未在 ListView Android 中激活
- excel - 循环用于函数的不同输入,然后在某个值处停止
- ansible - Ansible:调用按属性过滤的其他主机值
- c++ - C++ 中的客户端服务器传感器数据收集和 ROS
- javascript - 使用 Discord 机器人移动语音聊天用户
- php - 如何从单独的、导入的 services.yaml 中装饰服务?
- python - 在 Django 中将 UserCreationForm 添加到 html
- python - 使用谷歌云中的blob获取文件大小