我有一个Observable
协议:
/**
Conforming types gain the ability to add/remove observers, and send notifications to them.
*/
protocol Observable: AnyObject {
associatedtype ObserverType
var observers: [ObserverType] { get set }
}
该功能包含在扩展程序中:
extension Observable {
func addObserver(_ o: ObserverType) {
self.observers.append(o)
}
func removeObserver(_ o: ObserverType) {
// ...
}
/**
This is how you indicate which notification you wish to send.
This method takes in a block, which will receive your ObserverType.
Here you can call the particular method you want on the observer.
The block will be applied to all observers.
*/
func notify(_ block: (ObserverType) -> ()) {
for each in self.observers {
block(each)
}
}
}
这种设计的思想是,当一个对象被认为是有趣的时,我们将其制成Observable
,并将我们想要的每个通知作为方法放入协议中,并声明作为您的ObserverType
。您不能添加不符合该协议的观察者。
因此,假设我有一个名为Profile
的模型类。我将想要的通知放入协议:
protocol ProfileObserver {
func didReceiveImage(image: UIImage)
}
现在,我将使Profile
符合Observable
:
class Profile: Observable {
typealias ObserverType = ProfileObserver
var observers: [ProfileObserver] = []
/**
Just to demonstrate how you would send a particular notification to your observers.
*/
func foo() {
self.notify { (observer) in
observer.didReceiveImage(image: someImage)
}
}
}
一切正常。当我想向ObserverType
添加约束时会出现问题。
我想添加ObserverType
协议中的AnyObject
符合Observable
的约束条件:
associatedtype ObserverType: AnyObject
这是因为我想在removeObserver方法中使用===
运算符:
func removeObserver(_ o: ObserverType) {
let i = self.observers.firstIndex { $0 === o }
precondition(i != nil, "Attempted to remove an observer that wasn't even added")
self.observers.remove(at: i!)
}
但是编译器抱怨Profile
不符合Observable
,即使我使ProfileObserver
符合AnyObject
也是如此。
似乎为关联类型添加了约束,从而消除了为ObserverType
使用协议类型的能力。
例如,如果我制定了一些Foo
协议,并设定了约束条件:
associatedtype ObserverType: Foo
我不能使用符合Foo
的协议作为我的ObserverType
;它只会让我使用非协议类型,例如符合Foo
的结构或类。