Swift 将函数分配给保留闭包的对象时,如何捕获值
如果我有这样一门课:Swift 将函数分配给保留闭包的对象时,如何捕获值,swift,closures,block,reference-counting,Swift,Closures,Block,Reference Counting,如果我有这样一门课: class Example { var emptyBlock: (Void -> Void)? var string: String = "Here's some string" func someFunction() { let string = self.string print(string) } } 我在某一点上分配: let variable: Void -> Void = exampl
class Example {
var emptyBlock: (Void -> Void)?
var string: String = "Here's some string"
func someFunction() {
let string = self.string
print(string)
}
}
我在某一点上分配:
let variable: Void -> Void = exampleInstance.someFunction
exampleInstance.emptyBlock = variable
由于
variable
从someFunction
捕获exampleInstance
,并且变量
由exampleInstance
保留,我是否有一个保留周期?还是有什么魔法可以让这一切都不成问题呢?我做了一个快速的测试,我相信我已经证实了他们事实上是被怀疑抓获的。我将为其他有此问题的人发布我的发现:
以该类为例,在deinit
中设置断点:
class Example {
var emptyBlock: (Void -> Void)?
var string: String = "Here's some string"
func someFunction() {
let string = self.string
print(string)
}
deinit {
print("I was deinitialized") // Breakpoint Here
}
}
然后运行以下两个代码示例:
参考循环
不会命中断点,因为无法取消初始化:
let exampleInstance = Example()
let variable = exampleInstance.someFunction
exampleInstance.emptyBlock = variable
非参考循环
将命中断点,因为每周捕获:
let exampleInstance = Example()
let variable: Void -> Void = { [weak exampleInstance] in exampleInstance?.someFunction() }
exampleInstance.emptyBlock = variable
因为当我们弱捕获时它会到达断点,所以我们可以安全地得出结论,如果不这样做,它就会像一个闭包一样被强捕获
在使用这个工具时应该考虑到这一点,因为我们在声明闭包时并没有获得与捕获相同的明显性。没有明确的警告可以调用self
来提醒我们,在它们的范围内也没有弱声明
向导
我还在指南中找到了一个参考:
- 全局函数是具有名称且不捕获任何值的闭包
- 嵌套函数是具有名称的闭包,可以从其封闭函数中捕获值
- 闭包表达式是以轻量级语法编写的未命名闭包,可以从其周围的上下文中捕获值
是的,有一个循环。将某个变量赋给局部变量,然后再赋给其他变量,这与直接赋给它是一样的。所以这个代码相当于
exampleInstance.emptyBlock = exampleInstance.someFunction
而exampleInstance.someFunction
只是语法上的糖衣
{ x in exampleInstance.someFunction(x) }