一群在斯威夫特的弱观察者

the*_*tic 5 generics weak-references observer-pattern swift

我正在尝试实现一个允许我存储一组弱观察者的结构.

这是观察者包装器:

public func ==<T: Hashable>(lhs: WeakObserver<T>, rhs: WeakObserver<T>) -> Bool {
  return lhs.hashValue == rhs.hashValue
}

public struct WeakObserver<T where T: AnyObject, T: Hashable> : Hashable {

  private weak var weakObserver : T?

  public init(weakObserver: T){
    self.weakObserver = weakObserver
  }

  public var hashValue : Int {
    return self.weakObserver!.hashValue
  }

}
Run Code Online (Sandbox Code Playgroud)

这是每个观察者需要遵守的协议:

public protocol DataModelObserverProtocol : class, Hashable, AnyObject {

  func someFunc()

}
Run Code Online (Sandbox Code Playgroud)

用法:

public class DataModel: NSObject, DataModelInterface {

  public var observers = Set<WeakObserver<DataModelObserverProtocol>>()
  //^^^^^ Using 'DataModelObserverProtocol' as a concrete type conforming to protocol 'AnyObject' is not supported
}
Run Code Online (Sandbox Code Playgroud)

现在,虽然我知道这可能是Swift本身的限制,但我正在寻找一种替代解决方案,而没有具体的类作为类型约束(如果这不可能,我担心是这种情况,我仍然会喜欢获得替代的"非hacky"解决方案).

the*_*tic 0

我知道会有更好的方法来做到这一点,但对于这样一个简单的概念来说,它似乎太复杂了,所以我采用了不同的方法:

我只是使用NSNotificationCenter并重构了我的代码,使其不必具有紧密耦合的结构,因此我没有从通知中传递信息,而是设法以一种适合我的方式抽象它,即通知不需要传递参数给他们的观察者。由于通知仅支持通过userInfo字典传递信息,因此我不得不考虑这一点。

因此,正如我所提到的,我需要一种上下文解耦的方法来做到这一点。这是一个非常抽象的答案,但我认为它可能会帮助某人规避必须搞乱“功能失调的泛型”的问题。

为了通知我的观察者,我只需注册他们:

NSNotificationCenter.defaultCenter().addObserver(...)
Run Code Online (Sandbox Code Playgroud)

并发布不带参数的通知:

NSNotificationCenter.defaultCenter().postNotification...
Run Code Online (Sandbox Code Playgroud)

我已经在之前的项目中使用过内置函数NSNotificationCenter,并且我完全了解其内部工作原理,但最初我打算将信息传递给观察者,这就是为什么我想对它进行更多限制,以创建某种形式WeakSet

这在我的情况下再次起作用,因为我的观察者不一定需要传递可观察的细节,因为它通常是存在的并且可以被观察者访问(这是我的结构提供的东西,在读者的情况下可能不是这样) 。很难解释它,以便让阅读本文的任何人都有意义,但我对WeakSet提议的内容感到非常沮丧,所以我同意了。它更具可读性(尽管第三方可能不太容易理解),而且它似乎更适合我的用例。