From Swift 编程指南 - 闭包 https://docs.swift.org/swift-book/LanguageGuide/Closures.html
闭包可以从定义它的周围上下文中捕获常量和变量。然后,即使定义常量和变量的原始作用域不再存在,闭包也可以在其体内引用和修改这些常量和变量的值。
闭包捕获变量,而不是变量的内容。当我们谈论函数中的局部变量(通常在堆栈上分配)时,即使函数退出并且其他局部变量被释放,它也确保它们可以访问,因此我们可以这样做:
func myFunc() {
var array: [Int] = []
DispatchQueue.main.async {
// executed when myFunc has already returned!
array.append(10)
}
}
你的例子是类似的。闭包捕获变量。这是模块级别的变量,因此它的作用域始终存在。当你重新分配它的值时,它将影响闭包内读取的值。
或者,换句话说,闭包将相当于:
var closure = {
print(CurrentModule.element?.name ?? "default value")
}
where CurrentModule
是主模块的名称(通常是项目的名称)。
为了防止这种行为并捕获变量的值,我们可以使用关闭捕获列表。不幸的是,官方文档没有正确解释捕获列表到底是什么。基本上,使用捕获列表可以声明闭包的本地变量values创建闭包时可用。
例如:
var closure = { [capturedElement = element] in
print(capturedElement?.name ?? "default value")
}
这将创建一个新变量capturedElement
在闭包内,带有变量的当前值element
.
当然,通常我们只写:
var closure = { [element] in
print(element?.name ?? "default value")
}
这是[element = element]
.