为什么Swift闭包无法捕获自我? [英] Why Swift closure not capture self?

查看:92
本文介绍了为什么Swift闭包无法捕获自我?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Xcode游乐场测试快速关闭.

I was testing swift closure with Xcode playground.

这是我的代码:

import UIKit

class A{
    var closure: ()->() = {}

    var name: String = "A"
    init() {
        self.closure = {
            self.name = self.name + " Plus"
        }
    }

    deinit {
        print(name + " is deinit")
    }
}

var a: A?
a = A()
a = nil

不出所料,a是闭包自包含的,因此a不会被释放.

As what is expected, a is self contained by closure, so a is never released.

但是,当我在最后一行之前添加此行时:

But, when I add this line before the last line:

a?.closure = { a?.name = "ttt" }

然后,我在输出窗口中发现"A is deinit",这意味着a被释放. 为什么?是不可回收的参考吗?

Then, I found "A is deinit" in the output window, which means a is released. Why? is a not recycle reference?

为了测试,我使用一个函数来设置闭包,其代码为版本2:

To be test, I use a function to set the closure, which the code is version 2:

import UIKit

class A{
    var closure: ()->() = {}
    func funcToSetClosure(){
        self.closure = { self.name = "BBB"}
    }
    var name: String = "A"
    init() {
        self.closure = {
            self.name = self.name + " Plus"
        }
    }

    deinit {
        print(name + " is deinit")
    }
}



var a: A?


a = A()


a?.funcToSetClosure()


a = nil

同样,a永远不会被释放.

Again, a is never released.

所以我得出结论,当闭包是由init或类中的函数设置的时,它将导致回收引用,而当它在类之外被设置时,则不会导致回收引用.我说的对吗?

So I got the conclusion, when closure is set by init or a function in the class, it will cause recycle reference, when it is set out side the class, it will not cause recycle reference. Am I right?

推荐答案

在两种情况下都有保留周期.区别在于引用的性质,而不是设置了closure place .这种差异体现在中断周期所需的时间上:

There are retain cycles in both cases. The difference is the nature of the reference, not the place where closure is set. This difference is manifested in what it takes to break the cycle:

  • 在内部"情况下,闭包内部的引用为self.当您释放对a的引用时,即表示不足会中断该循环,因为该循环是直接自引用的.要中断周期,您还必须先 a.closure设置为nil,然后再将a设置为nil,但是您没有这样做.
  • In the "inside" situation, the reference inside the closure is self. When you release your reference to a, that is insufficient to break the cycle, because the cycle is directly self-referential. To break the cycle, you would have had also to set a.closure to nil before setting a to nil, and you didn't do that.

  • 在外部"情况下,引用为a.只要您的a引用未设置为nil,就会有一个保留周期.但是您最终要做将其设置为nil,这足以打破周期.
  • In the "outside" situation, the reference is a. There is a retain cycle so long as your a reference is not set to nil. But you eventually do set it to nil, which is sufficient to break the cycle.

(插图来自Xcode的内存图功能.太酷了.)

(Illustrations come from Xcode's memory graph feature. So cool.)

这篇关于为什么Swift闭包无法捕获自我?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆