【问题标题】:How to set a weak reference to a closure/function in Swift?如何在 Swift 中设置对闭包/函数的弱引用?
【发布时间】:2014-11-19 10:48:52
【问题描述】:

HMSegmentedControl 中,我想将segmentedControl.indexChangeBlock 设置为一个实例方法来处理该操作。 官方的例子是:https://github.com/HeshamMegid/HMSegmentedControl/blob/master/HMSegmentedControlExample/HMSegmentedControlExample/ViewController.m(第 63 ~ 68 行),但那是 Objective-C。

在 Swift 中,函数是一等公民。所以我想为这个块属性设置一个实例方法。
但是我的代码会导致循环引用,看来我应该定义一个弱引用:

class ExampleVC: UIViewController {
    var segmentedControlIndex: Int = 0

    override func viewDidLoad() {
      let segmentedControl3 = HMSegmentedControl(sectionImages: ... , sectionSelectedImages: ... )
      segmentedControl3.frame = ...
      segmentedControl3.indexChangeBlock = someInstanceMethod
    }

    func someInstanceMethod(index: Int) {
      segmentedControlIndex = index
    }
}

但是,我不能定义对非类类型的弱引用。我能做些什么?这样做合法吗?

【问题讨论】:

标签: ios swift closures


【解决方案1】:

[unowned self] 很危险。这样做是为了告诉运行时“假设 self 尚未被释放,不要担心检查。”如果self 在此期间确实被释放,您的应用程序将 SEGFAULT。

在这种情况下,{ [weak self] in self?.someInstanceMethod($0) } 将打破引用循环,如果self 被释放,则变为no-op

[weak self] 始终是安全的,而如果您修改代码的其他区域(例如视图层次结构),[unowned self] 可能会导致应用崩溃...

【讨论】:

  • HMSegmentedControl 归 ExampleVC 所有,因此您永远不会让 self 为零。正如 Apple 所说:尽可能使用 unowned。
  • Unowned 从根本上来说仍然是不安全的。我知道遵循 Apple 的建议是件好事,这可能是出于性能方面的原因,但我坚持我的建议,因为我概述的原因。
  • 我同意你的观点,弱者永远是安全的。关键是 unowned 不仅仅是假设它没有发布,更重要的是,作为开发人员,我说它永远不会为零。但我也同意你的观点,我宁愿 100% 确定,也不愿让别人说这是安全的,跳吧。
【解决方案2】:

您应该在闭包中使用"Capture List",而不是定义对闭包的弱引用。

segmentedControl3.indexChangeBlock = { [unowned self] in self.someInstanceMethod($0) }

据我所知,这是避免强引用循环的唯一方法。

【讨论】:

  • [weak self] 会破坏引用循环,并且在重构代码或重新组织视图层次结构时通常不太容易破坏。
猜你喜欢
  • 2015-08-18
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多