根据Apple Swift documentation:全局函数是具有名称且不捕获任何值的闭包。但是我在本书 IOS 11编程基础与Swift 中讨论了使用闭包的示例,它将全局函数A作为参数传递给另一个全局函数B进行修改全局变量x的值。该书指出A捕获X,这与Swift文档所说的相矛盾。
代码示例:
func pass100(_ f: (Int) -> ()) {
f(100)
}
var x = 0
print(x) // output 0
func setX(newX: Int) {
x = newX
}
pass100(setX)
print(x) //output 100
上面的代码片段在Xcode中工作,我很困惑。谁能解释一下这里发生了什么?
答案 0 :(得分:5)
This是“捕获”的意思:
闭包可以从定义它的周围上下文中捕获常量和变量。然后闭包可以引用并修改其体内的常量和变量的值,即使定义常量和变量的原始范围不再存在。
据说全局函数没有捕获任何东西,因为在程序运行时你永远不会离开全局范围,因此捕获任何东西都没有意义。如果它确实捕获了某些东西,那意味着即使在你以某种方式“离开”全局范围(可能程序完成运行)之后,全局变量仍然可以改变,这很奇怪。
代码中的全局函数没有捕获任何内容。它可以更改x
的值,因为x
仍在范围内。你没有离开全球范围。
答案 1 :(得分:0)
闭包可以从周围捕获常量和变量 定义它的上下文。
全球化,就像本地一样,是一种背景。 A
是一个全局函数,X
是一个全局变量;因此,A
会抓住X
。从技术上讲,应用程序中的所有方法都捕获X
,因为它在全局上下文中公开。然而,按照惯例,“捕获”通常指的是局部范围。
为了证明这一点,如果您将A
和X
移动到本地范围(例如类中的方法),则没有任何更改 - A
仍会捕获X
。您在示例中所做的全部工作都放在全局范围内,并且因为它们处于相同的范围(或上下文)中,所以捕获规则没有改变。
这是语义和惯例的问题,我认为这是一个Swift文档可能会有些误导的领域(如果我是Apple,我会改写它)。将函数从本地范围移动到全局范围绝不会改变其捕获能力。我认为Apple的意思是默认情况下,本地方法总是捕获一些东西(即使它是self
),而如果没有任何东西可以被捕获,则不保证全局函数捕获任何东西。