Swift中闭包的弱引用

7

我有以下代码用于创建可观察的属性以进行数据绑定。它还在开发中,所以我不确定最终实现会是什么样子,而且我对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
    }
}

我希望保留对观察者闭包的弱引用。我不想依赖客户端来确保通过捕获列表传递的闭包是弱引用/未拥有的。特别是因为在给定类上可以有许多可观察属性。
我的Observable类是否可以使闭包引用弱引用?
更新:
我找到了一些资源,我认为这些资源将帮助我实现我的目标: 使Swift方法中的self弱 具体来说,
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是可能的。 - Hai Feng Kao
2个回答

7
“在我的Observable类中,是否可能使闭包引用变得弱引用?” 答案是不可能。在Swift中,只有类实例可以通过弱引用引用,而函数不是类实例。(不仅如此,它们必须是Optional包装的类实例)。 当然,有一些很明显的解决方法-最简单的是使用包装器类。但在这种情况下,我并不建议这样做,因为您还没有让我相信在这里需要函数的弱引用。请记住,对于对象的弱引用,如果没有强引用,它们将立即失去引用,并指向nil。我不认为这是您想要的。我认为您在错误的方向上努力了。

最终,我希望观察者的生命周期与可观察类的生命周期无关。这里不是问题吗? - lintmouse
当然,这是一个问题。但这与函数引用弱有关并不大,与函数内部观察实例的引用弱有关。由调用者来指定“weak self”,就像你所说的一样;没有什么神奇的方法可以规避它(当然,将对函数的引用弱化并非一种神奇的方法来规避它)。 - matt
或者您可以非常明智地将 self.value 设为弱引用。这样,如果它恰好为 nil,则不会调用观察者。实际上非常简单。但也许这并不能解决问题,抱歉。 - matt

-2

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

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

如果您要在Objective-C中编写您正在编写的内容,您确实希望“Observable”对闭包具有强引用。否则,谁还会对闭包有强引用呢?


那么,一个Observable对象是否可以通过包含另一个对象传递的闭包来保持其生存?对我来说,闭包中捕获的引用似乎可以实现这一点。如果是这样,那么这就是我试图解决的问题。在.NET中,有弱事件模式,并且通常应用于数据绑定。尝试弄清楚Swift中是否也存在这个问题。 - lintmouse
为什么不先考虑如何使用 Objective-C 来实现呢?如果你使用 Objective-C,它会保持对闭包的强引用,闭包的提供者决定闭包对其他内容的引用是弱引用还是强引用。这些事情不应该由 Observable 决定,而应该由 Observable 的用户设计闭包以适应自己的需求。 - newacct
理想情况下,并不是每个监听器都必须实现弱观察者模式,它可以在像.NET中的WeakEventManager这样的中央位置进行管理。但我可能没有用Swift/Obj-C的方式思考这个问题,这就是我卡住的地方。 - lintmouse
- Alexander Volkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接