【问题标题】:How are values captured when assigning a function to something that retains a closure将函数分配给保留闭包的东西时如何捕获值
【发布时间】:2015-11-13 10:51:48
【问题描述】:

如果我有这样的课程:

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

我是否有一个保留周期,因为variablesomeFunction 捕获exampleInstance 并且variableexampleInstance 保留?或者是否有某种魔法使这不成问题?

【问题讨论】:

    标签: swift closures block reference-counting


    【解决方案1】:

    我做了一个快速测试,我相信我已经确认它们实际上被强烈捕获为可疑。我会将我的发现发布给其他有此问题的人:

    上这堂课,断点在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 来提醒我们,并且在它们的范围内没有弱声明。

    指南

    我还在指南中找到了参考:

    • 全局函数是具有名称但不捕获任何值的闭包。
    • 嵌套函数是具有名称的闭包,可以从其封闭函数中捕获值。
    • 闭包表达式是用轻量级语法编写的未命名闭包,可以从周围的上下文中捕获值。

    【讨论】:

      【解决方案2】:

      是的,有一个保留周期。给局部变量赋值,然后再赋值给其他变量,与直接赋值是一样的。所以该代码相当于

      exampleInstance.emptyBlock = exampleInstance.someFunction
      

      exampleInstance.someFunction 只是语法糖

      { x in exampleInstance.someFunction(x) }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-14
        • 2016-05-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多