gpt4 book ai didi

swift - 关于 [unowned self] 应该放在哪里的困惑

转载 作者:搜寻专家 更新时间:2023-10-31 08:05:47 25 4
gpt4 key购买 nike

我有一个保留循环,所以我的 viewcontroller 的 deinit 不会被调用,我试图通过添加 [unowned self] 来解决这个问题,但我不太确定在我的案例中将 unowned 放在哪里:

案例一

class YADetailiViewController: UIViewController {
var subscription: Subscription<YAEvent>?

override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
query, object in
DispatchQueue.main.async {
[unowned self] in// Put unowned here won't break the cycle, but it does compile and run
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}
}

案例2

 override func viewDidLoad() {
super.viewDidLoad()
if let query = self.event.subscribeQuery() {
self.subscription = Client.shared.subscribe(query)
self.subscription?.handle(Event.updated) {
[unowned self] query, object in // Put unowned breaks the cycle, and deinit is called
DispatchQueue.main.async {
self.pageViewLabel.text = String(object.pageViews) + " VIEW" + ((object.pageViews > 1) ? "S" : "")
}
}
}
}

我很好奇这两种情况之间有什么区别,以及为什么一个有效而另一个无效

最佳答案

的确,正如@matt 正确提到的,问题与 self 被捕获的时间有关。事实上,这段代码 self 被捕获了两次:

  • 当外层闭包传递给handle方法时
  • 当内部闭包传递给async方法时(在handle闭包执行期间)

外层闭包需要self将其传递给内层闭包,否则内层闭包将无法捕获它。

本质或保留循环如下:self(YADetailiViewController) -> subscription -> closure (handle parameter) -> self 。要打破这个循环,不在那个(外部)闭包中保留 self 就足够了。这就是第二个代码示例起作用的原因。

self 的第二次捕获(在内部闭包中)仅在执行外部闭包时发生并持续到执行该 async block - 通常它很短时间。

在第一个代码示例中,您没有打破循环。 self 的第二次捕获没有发生,但第一个(导致你的周期)仍然存在。

如果你的 handle 闭包在 View Controller 已经 deinited/released 时仍然可以调用,那么按照@AdrianBobrowski 的建议,你应该使用 weak 而不是 unowned 以防止可能的崩溃。

关于swift - 关于 [unowned self] 应该放在哪里的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48736870/

25 4 0
文章推荐: swift - 在 MacOS 上将 Vapor 编译为独立应用程序
文章推荐: java - "The type B cannot be a superinterface of C; a superinterface must be an interface"错误
文章推荐: java - 用于查找函数名称的 Eclipse 快捷方式
文章推荐: html - MSIE/Edge 将 HTTP HEAD 用于 数据 URL,然后将 204 响应视为错误?