【问题标题】:Function inside Function retain cycle函数内的函数保持循环
【发布时间】:2019-12-29 11:31:30
【问题描述】:

我想知道如何在以下情况下避免保留循环:

private func setupDismissCallbacks() {

  // inner func     
  func dismiss() {
     self.videoExporter?.cancel()
     self.rootViewController.dismiss(animated: true, completion: nil)
     self.delegate?.childCoordinatorDidFinish(self)
  }

  // first clousre       
  saveModalViewController.onButtonDismiss = {  [weak self] in
     // not really using `self` here
     guard let self = self else { return }
     dismiss()
  }

  // second clousre  
  saveModalViewController.onDimmedAreaDismiss = { [weak self] in
     // not really using `self` here
     guard let self = self else { return }
     dismiss()
  }

}

我有一个函数setupDismissCallbacks,它监听来自saveModalViewController 自属性的两个回调。 dismiss()setupDismissCallbacks 内部的一个内部函数,我用来访问 self 值。

但在 onButtonDismissonDimmedAreaDismiss 闭包中,我无法访问 self 来调用 dismiss,我无法将 [weak self] 添加到 dismiss 函数中,因为它是一个函数。

如何验证dismiss 内部的调用不会导致保留循环?

【问题讨论】:

  • "我不访问 self 来调用 dismiss" 你认为 dismiss() 调用如何知道要操作哪个实例? IE。当它被调用时,它的self 的值是多少?
  • @Alexander 不是类函数,调用self.dismiss()会得到Value of type 'SaveCoordinator' has no member 'dismiss'
  • @Alexander 在函数内部
  • 哦,我没注意到。你的内在功能捕捉自我。您的两个闭包捕获了该内部函数(包括它所包含的上下文,其中包括self)。由于saveModalViewController 强烈引用了您的两个闭包(我假设self 强烈引用了这两个闭包),因此您有一个保留周期。
  • 有办法避免吗?我正在尝试减少重复代码。一个想法是简单地将dismiss() 放在类范围内,但是类可能有一些dismiss 选项,因此将其保留在函数中使其保持在上下文中,由于创建保留周期

标签: ios swift weak-references retain-cycle weak


【解决方案1】:

只需将您的闭包分配给一个局部变量。此时,提取出dismiss 是没有意义的,所以只需内联它:

private func setupDismissCallbacks() {     
    let dismissCallback: () -> Void = {  [weak self] in
        guard let self = self else { return }
        self.videoExporter?.cancel()
        self.rootViewController.dismiss(animated: true, completion: nil)
        self.delegate?.childCoordinatorDidFinish(self)
    }

    saveModalViewController.onButtonDismiss = dismissCallback
    saveModalViewController.onDimmedAreaDismiss = dismissCallback
}

【讨论】:

  • 为什么要加倍 = = 和我中间的空格。
  • @kjoe 这是一个错字
  • 看起来很准确@Alexander - 谢谢!正是我想要做的事情
【解决方案2】:

@Alexander 在 cmets 中解释了这个问题:

您的内部函数捕获self。你的两个闭包捕捉到了 内部函数(包括它所包含的上下文,其中包括 self)。由于您的两个闭包被强烈引用 saveModalViewController(我认为它被 self),你有一个保留周期。

您可以通过不让dismiss 捕获self 来打破这个循环。将SaveCoordinator 传递给dismiss

private func setupDismissCallbacks() {     
  func dismiss(_ coordinator: SaveCoordinator) {
     coordinator.videoExporter?.cancel()
     coordinator(animated: true, completion: nil)
     coordinator.delegate?.childCoordinatorDidFinish(coordinator)
  }

  // first clousre       
  saveModalViewController.onButtonDismiss = {  [weak self] in
     guard let self = self else { return }
     dismiss(self)
  }

  // second clousre  
  saveModalViewController.onDimmedAreaDismiss = { [weak self] in
     guard let self = self else { return }
     dismiss(self)
  }

}

【讨论】:

  • 干燥。只需将重复的闭包提取到一个变量中,然后分配两次。
  • 也考虑过 - 谢谢你的回答 - 似乎它取决于场景,但亚历山大解决方案更适合这个。再次感谢您!
猜你喜欢
  • 2021-04-04
  • 1970-01-01
  • 1970-01-01
  • 2014-02-13
  • 2013-09-09
  • 1970-01-01
相关资源
最近更新 更多