【问题标题】:weak Delegate and class protocol弱委托和类协议
【发布时间】:2016-09-16 01:56:04
【问题描述】:

在调用dismissViewControll 后,我一直在使用协议和委托方法将数据传回之前的VC。以下是我通常会这样做,因为大多数教程都不是这样写的

protocol someVCDelegate {
    func somefunction()
}

var delegate: someVCDelegate!

但是,我遇到了这个类/编写它的弱方法。

protocol someVCDelegate : class {
    func somefunction()
}

weak var delegate: someVCDelegate!

我了解 weak 与 ARC 相关联并避免了保留周期。但是,我不确定什么时候需要它,就像在所有情况下一样,不做弱委托工作(VC 确实 deinit)。在什么样的情况下我需要弱委托?还有,为什么是“!”弱之后,通常是“?”后弱吧?

【问题讨论】:

  • 你在任何时候都会让代表为零吗?还是上一个 VC 不保留对下一个 VC 的引用?我怀疑为什么要在任一 VC 上调用 deinit,如果一个对象至少有一个对其的强引用,ARC 不会清理它。因此,如果前一个 VC 具有对下一个 VC 的引用,并且下一个 VC 具有对前一个的(强)委托引用,如果它们丢失所有其他引用导致内存泄漏,ARC 将不会删除它们
  • 无论如何让代理变弱总是好的做法,这并不困难,并且可以在将来为您省去一些麻烦。如果以后确实成为问题,可能很难调试
  • 今天刚读完。它澄清了一些松散的结局:对我来说是ARC。 raywenderlich.com/134411/arc-memory-management-swift

标签: ios swift delegates protocols swift-protocols


【解决方案1】:

你说:

但是,我不确定什么时候需要它,就像我所有的情况一样,不做弱委托工作

只有当你有潜在的强引用循环时,你才需要弱协议委托模式,即强引用的循环系列。例如,考虑:

  • 具有属性(“子”)的对象(“父”),即父具有对子的强引用;

  • 孩子有一个delegate 属性;和

  • 您将子对象的delegate 设置为引用父对象。

在这种情况下,代理必须是 weak 引用,否则您将有一个强大的引用循环。

注意,这是一个简单的例子,有时强引用链可能相当复杂。例如,考虑具有委托属性的UIView 子类。潜在的强引用周期可能相当长,从视图控制器到其根view,通过一系列子视图的子视图,一直到UIViewdelegate,这可能会潜在地引用回视图控制器。这也将导致强大的引用周期,因此我们倾向于使用weak 引用delegate

但是,当您使用协议委托模式在视图控制器之间传递数据时,这通常不是问题(视图控制器包含除外),因为呈现视图控制器不拥有呈现的视图控制器。视图控制器层次结构通常维护对视图控制器的强引用。因此,当您关闭呈现的视图控制器时,它会被释放,并且潜在的强引用循环被解决。

通常,我们会本能地使用weak 协议委托模式(仅仅是因为它完全防止了强引用循环的发生)。但有时你会使用强引用。最常见的强引用模式是NSURLSession,其delegate 是强引用。正如documentation for init(configuration:delegate:delegateQueue:) 警告我们的那样:

会话对象保持对delegate 的强引用,直到您的应用退出或显式使会话无效。如果您没有通过调用invalidateAndCancel()finishTasksAndInvalidate() 方法使会话无效,则您的应用会泄漏内存直到退出。

虽然这看起来很矛盾,但这种强引用模式的优点是会话知道它可以安全地调用其委托方法,而不必担心对象已被释放。 (顺便说一句,NSURLSession 这种强大的委托行为很少引起丑陋的头,因为我们经常使用完成处理程序方法,根本不使用委托方法,当我们使用委托方法时,我们经常有一些视图控制器以外的对象作为会话的委托。)

简而言之,您确实必须评估每种情况,并确定我们本能倾向于使用的弱参考是否更好,或者您是否有一种情况,您的协议可以更好地使用强参考。

【讨论】:

    【解决方案2】:

    为什么它是弱的:弱引用是一种不会对它所引用的实例保持强控制的引用,因此不会阻止 ARC 处理被引用的实例。此行为可防止引用成为强引用循环的一部分。或者简单地说,您可以通过将类之间的一些关系定义为弱引用或无主引用而不是强引用来解决强引用循环。

    它是“!”在弱之后,因为它是隐式展开的。它会有一个价值。

    有时从程序的结构中可以清楚地看出,在第一次设置该值之后,可选项总是有一个值。在这些情况下,无需在每次访问可选值时检查和解开它的值,因为可以安全地假定它始终具有值。

    【讨论】:

      猜你喜欢
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多