Swift保留循环说明

Yan*_*iao 9 iphone ios swift swift2

这是我的自定义视图:

class CustomVIew: UIView {

    deinit {
        print("custom view deinit")
    }

    var onTapViewHandler: (()->Void)?
}
Run Code Online (Sandbox Code Playgroud)

和视图控制器:

class ViewControllerB: UIViewController {

    var customView: CustomVIew!

    deinit {
        print("B deinit")
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        let customView = CustomVIew()
        customView.onTapViewHandler = { [unowned self] in
            self.didTapBlue()
        }
        customView.frame = CGRect(x: 50, y: 250, width: 200, height: 100)
        customView.backgroundColor = UIColor.blueColor()
        view.addSubview(customView)

        self.customView = customView

    }

    func didTapBlue() {

    }
}
Run Code Online (Sandbox Code Playgroud)

当控制器从导航堆栈中弹出时,一切都很好:

B deinit
custom view deinit
Run Code Online (Sandbox Code Playgroud)

但是当我替换这段代码时:

customView.onTapViewHandler = { [unowned self] in
     self.didTapBlue()
}
Run Code Online (Sandbox Code Playgroud)

有了这个:

 customView.onTapViewHandler = didTapBlue
Run Code Online (Sandbox Code Playgroud)

然后,控制台上没有任何内容.CustomView和ViewController没有发布,为什么?

为什么要customView.onTapViewHandler = didTapBlue捕获引用self

ren*_*thr 6

Swift函数是一种闭包.就像闭包(目标c中的块)一样,函数可以捕获引用.

customView.onTapViewHandler = didTapBlue得到执行参考self,即ViewControllerB在这种情况下将参考由所述函数调用被捕获.

同一时间ViewControllerB的观点有很强的参考价值,CustomVIew因此它保留了周期.

关于使用unowned,Apple文档说:

弱引用和无引用引用使引用周期中的一个实例能够引用另一个实例而不保持强大的保持.然后,实例可以相互引用而不会创建强大的参考周期.

这意味着没有循环引用和保留循环.


Swe*_*per 5

如果添加了[unowned self]捕获列表关闭,观点持有弱引用self,并self拥有强大的参考视图。

由于没有对的强烈引用selfself因此在弹出视图控制器时可以取消初始化。在self取消初始化之后,不再有任何对视图的强大引用,因此也对其进行了取消初始化。

如果删除捕获列表,则self对视图具有强引用,而视图对则具有强引用self。这意味着self要取消初始化,必须先将视图取消初始化(这将破坏强引用)。但是,为了取消视图的初始化,必须先将视图控制器取消初始化,以打破对视图的强引用。但是除非取消初始化视图控制器,否则您不能破坏对视图的强引用。除非取消初始化视图,否则您不能破坏对视图控制器的强引用。

看到?我们在这里陷入了无限循环!因此,视图和视图控制器都不会被初始化!