Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 将函数分配给保留闭包的对象时,如何捕获值_Swift_Closures_Block_Reference Counting - Fatal编程技术网

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) }