swift2 Swift保留周期说明

gg58donl  于 2022-11-06  发布在  Swift
关注(0)|答案(2)|浏览(183)

以下是我的自定义视图:

class CustomVIew: UIView {

    deinit {
        print("custom view deinit")
    }

    var onTapViewHandler: (()->Void)?
}

和视图控制器:

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() {

    }
}

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

B deinit
custom view deinit

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

customView.onTapViewHandler = { [unowned self] in
     self.didTapBlue()
}

与此:

customView.onTapViewHandler = didTapBlue

那么,控制台上什么也不打印。2 CustomView和ViewController没有发布,为什么?
为什么customView.onTapViewHandler = didTapBlue捕获对self的引用?

eeq64g8w

eeq64g8w1#

Swift函数是闭包的一种,所以像闭包一样,函数也可以捕获引用。
customView.onTapViewHandler = didTapBlue执行时,对self的引用,即在这种情况下的ViewControllerB引用将由函数调用捕获。
同时,ViewControllerB的视图保持对CustomVIew的强引用,因此它进行保留循环。
关于使用unowned,Apple文档中指出:
弱引用和无主引用使引用循环中的一个示例能够引用另一个示例,而无需保持对它的强控制。然后,示例可以相互引用,而无需创建强引用循环。
这意味着没有循环引用和保留循环。

vs3odd8k

vs3odd8k2#

如果将[unowned self]捕获列表添加到闭包中,则视图将保存对self的弱引用,而self将保存对该视图的强引用。
由于没有任何东西对self有强引用,所以当视图控制器弹出时,self可以被取消初始化。在self被取消初始化后,没有任何东西对视图有强引用,所以 it 也被取消初始化。
如果删除捕获列表,则self将保留对视图的强引用,而视图将保留对self的强引用。这意味着要取消初始化self,必须先取消初始化视图(这将破坏强引用)。但是为了使视图被取消初始化,必须先取消视图控制器的初始化,以中断对视图的强引用。但是,除非取消视图控制器的初始化,否则无法中断对视图的强引用。您可以'除非取消初始化视图,否则不要中断对视图控制器的强引用。
看到了吗?我们在这里陷入了一个无限循环!所以视图和视图控制器都不会被取消初始化!

相关问题