swift - Swift 中的一组弱观察者

标签 swift generics observer-pattern weak-references

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

这是观察者包装器:

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
  }

}

这是每个观察者都需要遵守的协议(protocol):

public protocol DataModelObserverProtocol : class, Hashable, AnyObject {

  func someFunc()

}

用法:

public class DataModel: NSObject, DataModelInterface {

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

现在,虽然我知道这可能是 Swift 本身的限制,但我正在寻找一个没有具体类作为类型约束的替代解决方案(如果那不可能,恐怕就是这种情况,我'我仍然喜欢获得替代的“非 hacky”解决方案)。

最佳答案

使用 Set 来保存引用存在一个风险,即 Set 最终将需要使用其 hashValue 来引用一个元素,并且当弱引用变为 nil 时,hashValue 函数将崩溃。

我无法使用协议(protocol)来做到这一点,但我找到了一种使用返回函数元组的通用函数来获得类似功能的方法。

struct WeakReference<T>
{
    weak var _reference:AnyObject?
    init(_ object:T) {_reference = object as? AnyObject}
    var reference:T? { return _reference as? T }
}

func weakReferences<T>(_:T.Type) -> ( 
                                     getObjects: ()->[T],
                                     addObject:  (T)->()
                                    )
{  
   var references : [WeakReference<T>] = []

   func getObjects() -> [T]
   { 
      return references.filter({ $0.reference != nil }).map({$0.reference!}) 
   }

   func addObject(object:T)
   { 
      if getObjects().contains({ ($0 as! AnyObject) === (object as! AnyObject) }) 
      { return }
      references.append(WeakReference(object)) 
   } 

  return (getObjects:getObjects, addObject:addObject)   
}

public protocol DataModelObserverProtocol: class, AnyObject
{
   func someFunc() -> String
}

public class DataModel: NSObject, DataModelInterface  
{
   var observers = weakReferences(DataModelObserverProtocol)
}

要添加观察者,您可以使用:

observers.addObject( yourObserver )

遍历观察者:

for observer in observers.objects()
{
   observer.someFunc()
}

这两个函数都是类型安全的,并且只会接受/返回符合 DataModelObserverProtocol 的对象

关于swift - Swift 中的一组弱观察者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34827198/

相关文章:

arrays - 如何将扩展添加到 Swift 数组以有条件地追加?

javascript - 在两个解耦的 javascript 模块之间传输数据的 PubSub 模式替代方案

ios - 滚动到 CollectionView 底部时,Collection View Cell 会无意中调整大小

ios - 具有贝塞尔曲线路径的 SCNShape

C++ 泛型类——分离接口(interface)和实现

c# - 仿函数什么时候应该使用它们它们的预期用途是什么

java - 这是使用接口(interface)回调的正确方法吗?

oop - 如何为观察者系统创建这种接口(interface)?

ios - 在 Core Image 中设置过滤器值会导致崩溃。 - swift

ios - 使用 GCD 等待异步函数完成