gpt4 book ai didi

swift - 关于 swift Closure 的一个有趣现象

转载 作者:搜寻专家 更新时间:2023-11-01 06:32:35 24 4
gpt4 key购买 nike

我在 Controller 中有一个类对象,然后我在这个对象中有一个闭包。我将 Controller 的一个功能分配给对象的闭包,然后页面不会取消初始化。

我该如何解决这个问题?

import UIKit

class SecondViewController: UIViewController {
let test = TestObject()

override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.white
self.test.select = self.selectButton(index:)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.test.doSomethine()
}

func selectButton(index:Int){
print(index)
}

deinit {
print("deinit")
}
}

import UIKit

typealias selectBtnBlock = (_ index:Int)->()

class TestObject: NSObject {
var select:selectBtnBlock?

func doSomethine(){
self.select!(1)
}
}

最佳答案

这是因为当您执行以下操作时,您的test 对象的选择闭包强烈 捕获了您的SecondViewController:

self.test.select = self.selectButton(index:)

我建议您通过 Apple 的 Swift 语言引用阅读一些关于弱类型和强类型的内容。您遇到的“有趣现象”称为强引用循环。

本质上,由于 Swift 使用 ARC 作为其内存管理模型,任何被至少一个其他对象引用的对象都将保持事件状态,并且其内存不会被释放。

在你的例子中,test 已经通过我提到的行捕获了它的父级 SecondViewContoller。这意味着您遇到如下情况:

SecondViewController -> (owns) test // since its a member of the class
test -> (strongly captures) SecondViewController // via the assignment

这会导致两者之间形成强引用循环,并且不允许 ARC 解除分配。

当它 (ARC) 尝试释放 test 时,它知道 SecondViewController 引用了它,因此只有当父级也被释放时它才能被释放。当它尝试释放 SecondViewController 时,ARC 知道该对象被 test.select 闭包引用。

因为两者的引用计数都大于 1,所以都不会被释放。

解决您的问题的一种方法是编写:

self.test.select = { 
[weak self] // weakly capture self, this prevents a ref cycle
(i:Int)->() in // a closure that accepts an Int
guard let s = self else { return } // check if self is not nil
s.selectButton(index: i) // finally invoke the required method
}

另一种方式,类似的意图:

self.test.select = { [weak self] i in
self?.selectButton(index: i)
}

此上下文中的 weak 关键字用于告诉 Swift 编译器我不想保留对我正在捕获的内容的强引用(在本例中为 self ).

关于swift - 关于 swift Closure 的一个有趣现象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45180646/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com