从Apple Swift编程指南(2.2)中可以看出
闭包可以从定义它的周围上下文中捕获常量和变量。然后闭包可以引用并修改其体内的常量和变量的值,即使定义常量和变量的原始范围不再存在。
示例:
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30
问题是如何保存值而不是重置?我来自C背景,这看起来像3个函数调用和3个不同的堆栈帧。但价值似乎没有被覆盖。这是否意味着如果闭包使用其周围的上下文变量,它不会被编译器擦除,如果使用不正确会导致内存泄漏?
答案 0 :(得分:2)
这是否意味着如果闭包使用其周围的上下文变量,它不会被编译器擦除,如果使用不正确会导致内存泄漏?
当然,但这不是在这种情况下发生的事情。让我分解一下。从makeIncrementer
函数开始:
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
现在考虑周围函数 声明 最后一行调用 但是只要func incrementer
指的是runningTotal
,它位于自己身体外的范围内。因此,runningTotal
。{/ 1>
func incrementer
的作用:makeIncrementer
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
// ...
func incrementer() -> Int {
// ...
}
return incrementer
}
并将其返回。所以现在考虑当我们调用周围的函数时会发生什么:func incrementer
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
// ...
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
,我们刚刚说过它会返回一个函数。它还将该函数分配给变量makeIncrementer
。这是本地(自动)变量。所以,是的,这个函数被保留,但只有incrementByTen
存在,这不会很长,因为它只是作为一个自动局部变量在堆栈上。incrementByTen
生存,它就会保留该功能,而我们在开始时说的那个功能已经捕获了incrementByTen
并且正在维护它一种浮动的局部空间。因此runningTotal
指向的函数可以多次调用,浮动incrementByTen
可以保持生存并不断增加。