【问题标题】:Passing self and returning it in a closure without retain cycle传递 self 并在没有保留循环的情况下在闭包中返回它
【发布时间】:2019-10-15 23:56:23
【问题描述】:

我厌倦了在闭包中使用 [weak self] 捕获,所以我想传递 self 并在闭包中返回它,如下所示:

alertManager.askToConfirm(from: self) { vc, confirmed in
        if confirmed {
            vc.model.confirm()
        } else {
            vc.model.reject()
        }
    }

AlertManager 里面我的代码是这样的:

func askToConfirm<T>(from vc: T, completion: @escaping (T) -> ()) {
    let invitation = pageItemFactory.createConfirmationPageItem() { [weak self] accepted in
        self?.dismissAlert()
        completion(vc, accepted)
    }
    present(invitation)
}

这会创建一个保留周期吗?

【问题讨论】:

  • 99% 的情况下,如果您使用内联闭包并且被调用的函数只是将传递的闭包保存在局部变量中(而不是将其存储在属性中),则不会有保留循环并且不需要weak self
  • @Paulw11 我什么时候需要在createConfirmationPageItem() 块中使用[weak vc]?我只是在想这可能会捕获 vc 并导致某种循环
  • 所以我只是尝试了这个,结果我必须将 [weak vc] 放在 createConfirmationPageItem() 块中,因为它捕获了对它的强引用。

标签: ios swift memory closures


【解决方案1】:

不,据我所知,这不会导致保留周期。


例如,这导致一个保留周期。当myFunction 执行时,Foo 实例将持有对completion 块的强引用。反过来,completion 块拥有对Foo 实例的强引用。这将是一个保留周期,在这种情况下您需要添加一个捕获列表。

class Foo<T> {
  var completion: (T) -> ()

  func myFunction(_ vc: T, completion: @escaping (T) -> ()) {
    self.completion = completion // This will create a retain cycle
    completion(vc)
  }

  func doSomething() { 
    myFunction(self) { vc in
      print(vc)
    }
  }
}

【讨论】:

  • 嗯,我见过一些框架返回vc而不需要添加[弱自我]。他们是怎么做到的呢?本文中addPlaybackStartedObserver 的示例:swiftbysundell.com/posts/observers-in-swift-part-2
  • 这取决于上下文。即使vc 被保留,也不意味着它会导致一个保留周期。您的示例不会导致保留周期,除非vc 持有对闭包本身的强引用。 (我已经更新了我的答案,使其更加清晰和正确。)
  • 我的闭包函数实际上在另一个类中。 Self 持有对调用它的这个类的强引用。
  • 我添加了一个示例。你能发布你的完整代码吗?这样更容易判断是否创建了循环。
  • 不,据我所知,这不会导致保留周期。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-30
  • 2011-11-16
  • 2011-05-20
  • 1970-01-01
相关资源
最近更新 更多