【问题标题】:Weak reference to closure in SwiftSwift 中对闭包的弱引用
【发布时间】:2015-08-18 11:24:28
【问题描述】:

我有以下代码来创建数据绑定的可观察属性。它正在开发中,所以我不确定最终的实现会是什么,而且我对 Swift 还是很陌生。

class Observable<T> {
    typealias Observer = T -> Void

    var value: T {
        didSet {
            for observer in self.observers {
                observer?(self.value)
            }
        }
    }

    var observers: [Observer?] = []

    init(_ val: T) {
        self.value = val
    }
}

我想保留对 Observer 闭包的弱引用。我不想依赖客户端在通过捕获列表传递它之前确保闭包是弱/无主的。特别是因为给定的类可以有许多可观察的属性。

是否可以在我的 Observable 类中使闭包引用变弱?

更新:

我发现了一些我认为可以帮助我实现我想要的资源:

Make self weak in methods in Swift

具体来说,

func methodPointer<T: AnyObject>(obj: T, method: (T) -> () -> Void) -> (() -> Void) {
  return { [unowned obj] in method(obj)() }
}

以下链接引用了上面的 stackoverflow 答案并更详细地介绍了:

http://blog.xebia.com/2014/10/09/function-references-in-swift-and-retain-cycles/

这是一个双向绑定示例:

http://five.agency/solving-the-binding-problem-with-swift/

具体来说,

class BondBox<T> {
  weak var bond: Bond<T>?
  init(_ b: Bond<T>) { bond = b }
}

侦听器被包装在一个名为 Bond 的类中,该类在 BondBox 中被弱引用。

【问题讨论】:

  • 我认为 swift 5.2 的callAsFunction 是可能的

标签: swift closures weak-references


【解决方案1】:

是否可以在我的 Observable 类中使闭包引用变弱

没有。在 Swift 中,只有类实例可以通过弱引用来引用,并且函数不是类实例。 (而且它们不仅必须是类实例,还必须是包装类实例的 Optional。)

有一些非常明显的方法可以解决这个问题,或者当然 - 最简单的是包装类。但在这种情况下,我实际上并不建议这样做,因为您并没有让我相信,这里首先需要对函数的弱引用。请记住,对没有强引用的对象的弱引用将立即失去引用并指向 nil。我不敢相信那是你想要的。我想你在这里叫错了树。

【讨论】:

  • 最终我希望观察者的生命周期独立于可观察类的生命周期。这不是问题吗?
  • 当然是个问题。但这与对 function 的引用很弱无关。它与对函数内部观察到的实例的引用很弱有关。正如您所说,由来电者说weak self;没有什么神奇的方法(当然,使对函数的引用变弱并不是一种神奇的方法)。
  • 或者你可以非常明智地让self.value变弱。所以如果它碰巧是 nil 你就不会打电话给观察者。其实很简单。但也许这并不能解决问题,抱歉。
【解决方案2】:

Weak/strong 用于对象的内存管理,因此仅适用于引用类型的变量(即指向对象的类型)。 Swift 中的函数类型不是引用类型,因此为它们的变量谈论弱/强是没有意义的。

另外,您的代码中实际上并没有函数类型的变量(迭代中间除外)。你只需要一个数组类型的变量。即使在 Objective-C 中,您也只能将变量标记为弱或强,而不是存储在其他事物中的值。

如果你要用 Objective-C 写你正在写的东西,你会希望“Observable”对闭包有很强的引用。否则,谁还有会强烈引用闭包?

【讨论】:

  • 那么一个 Observable 对象是否可以纯粹通过包含另一个对象传入的闭包来保持另一个对象的存活?对我来说,闭包中捕获的引用似乎使这成为可能。如果是这样,那么这就是我要解决的问题。 .NET 中有弱事件模式,通常应用于数据绑定。试图弄清楚这是否也是 Swift 中的一个问题。
  • @dustmouse:你为什么不首先考虑如何在Objective-C中做到这一点。如果你在 Objective-C 中这样做,它将保持对闭包的强引用,并且闭包的提供者决定闭包是对其他事物的弱引用还是强引用。不应该由 Observable 来决定这些事情;应该由 Observable 的用户来设计闭包以满足其需求。
  • 理想情况下,不是每个侦听器都必须实现弱观察者模式,它可以在 .NET 中的 WeakEventManager 等中心位置进行管理。但我可能不会以 swift/obj-c 的方式考虑这个问题,这就是我所关注的。
猜你喜欢
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 2019-07-18
相关资源
最近更新 更多