【发布时间】:2020-08-29 22:17:25
【问题描述】:
我正在尝试使用SE-0142 (Associated Type Constraints) 来创建具有 2 个协议的观察者模式,IsObserver(如客户端)和 HasObservers(如服务器),其中有一个共享的 DataType 表示类型被观察的事物。
我需要符合HasObservers 的对象才能成为结构或类,并且我希望有意将IsObserver 限制为类(想要,但不需要)。
我不擅长泛型......几个小时后,我走到了这一步,编译器错误在下面的内联评论中。我被困住了,不知道下一步该去哪里,而且我不确定这种方法是否可行或合理。非常感谢所有帮助!
import Foundation
protocol IsObserver: class {
associatedtype DataType
func dataDidUpdate(_ data: [DataType])
}
struct Observation<T: IsObserver> {
weak var observer: T?
}
protocol HasObservers {
associatedtype DataType : IsObserver where DataType.DataType == DataType
static var observations: [ObjectIdentifier : Observation<IsObserver>] { get set } // ERROR: "Value of protocol type 'IsObserver' cannot conform to 'IsObserver'; only struct/enum/class types can conform to protocols"
static func tellObserversDataDidUpdate(_ data: [DataType])
}
extension HasObservers {
static func tellObserversDataDidUpdate(_ data: [DataType]) {
for (id, observation) in observations {
guard let observer = observation.observer else {
observations.removeValue(forKey: id)
continue
}
observer.dataDidUpdate(data)
}
}
static func addObserver<T: IsObserver>(_ observer: T) {
let id = ObjectIdentifier(observer)
let ob = Observation.init(observer: observer)
observations[id] = ob
}
static func removeObserver<T: IsObserver>(_ observer: T) {
let id = ObjectIdentifier(observer)
observations.removeValue(forKey: id)
}
}
UPDATE:好的,终于到了。比我想象的要难,需要类型擦除。在这个要点中,有两个版本:第一个版本是根据原始问题具有相关类型协议的版本。但它是有限的——作为观察者的对象只能观察一种类型。所以我做了另一个变种,它可以有多种类型但不使用 associatetype 协议,所以观察者必须手动检查类型。
https://gist.github.com/xaphod/4f8a6402429759b6b3fd8ea2d8ea53c4
【问题讨论】:
-
@Jessy 目光短浅:我们大多数人都有需要支持的专业应用程序,当然在某些情况下必须一直支持到 iOS 9。另外,Combine 不是 Apple 特有的吗?如果我想在服务器上这样做呢?
-
@Jessy 嗯,你可能是个业余爱好者,但我们中的一些人以此为生。专业领域对 iOS12 的支持不是可选的
-
@xaphod 观察与观察有什么用?也许我没有关注
-
@NewDev 我不确定我是否理解你的问题,你的意思是为什么
struct Observation存在?这是因为我想对观察者有一个弱内存引用,以防它是一个需要 deinit 的类
标签: swift protocols associated-types