我正在尝试实现一个允许我存储一组弱观察者的结构。
这是观察者包装器:
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/