我正在尝试构建一个发布者/观察者系统,以便轻松观察来自 API 的数据更改并通过应用程序发布有关控制器的信息。
我到目前为止的观点只是为单次观察工作。但是今天我遇到了一个问题,该问题阻止 UIViewController
观察多个 Publisher
。
我不是为了防止混淆而分享整个代码,我认为下面的问题是主要原因。如果有解决方案,那么我的问题就解决了。
protocol Base {
associatedtype BaseType
}
protocol One: Base where BaseType == String {}
protocol Two: Base where BaseType == Int {}
class BaseClass {}
extension BaseClass: One {
typealias BaseType = String
}
extension BaseClass: Two {}
当我尝试扩展 BaseClass
以符合 Two
时,它抛出
'Two' requires the types 'BaseClass.BaseType' (aka 'String') and 'Int' be equivalent
Base
协议中有其他方法,它们依赖于 BaseType
参数。但正如我之前所说,我不认为这是问题所在。
有什么建议吗?
更新:用例的更多细节
我的基本协议如下;
protocol Publishable {
associatedtype Publisher: Service
}
protocol Service {
associatedtype Publishing: Publishable
var data: Publishing? { get set }
var observers: [AnyObserver<Publishing>] { get set }
func publish(_ data: Publishing)
func add(_ observer: AnyObserver<Publishing>)
}
protocol Observer {
associatedtype ObservingType: Publishable
func subscribe(toService service: ObservingType.Publisher)
func received(_ data: ObservingType)
}
然后我需要一个解决方案,将符合 Observer 的不同类型添加到同一个数组中。应用类型擦除;
struct AnyObserver<Observing: Publishable>: Observer {
private let _subscribe: (Observing.Publisher) -> Void
private let _received: (Observing) -> Void
init<Base: Observer>(_ base: Base) where Observing == Base.ObservingType {
_received = base.received
_subscribe = base.subscribe
}
func subscribe(toService service: Observing.Publisher) {
_subscribe(service)
}
func received(_ data: Observing) {
_received(data)
}
}
之后我们的用例就在这里。假设我们有一个 AViewController
,它需要来自 API 的 Book
和 Movie
的数据。我没有包括 API 部分,因为它是另一层。
struct Book: Codable {
var name: String?
var author: String?
}
struct BookList: Codable {
var data: [Book]?
var status: Int?
}
extension BookList: Publishable {
typealias Publisher = BookListService
}
struct Movie: Codable {
var name: String?
var director: String?
}
struct MovieList: Codable {
var data: [Movie]?
var status: Int?
}
extension MovieList: Publishable {
typealias Publisher = MovieListService
}
Publishable
扩展了 BookList
和 MovieList
,因为它们需要携带有关哪个 Service
对象可以发布它们的信息。 BookListService
和 MovieListService
声明如下;
class BookListService: Service {
var data: BookList?
var observers: [AnyObserver<BookList>] = []
func publish(_ data: BookList) {
//publish
}
func add(_ observer: AnyObserver<BookList>) {
observers.append(observer)
}
}
class MovieListService: Service {
var data: MovieList?
var observers: [AnyObserver<MovieList>] = []
func publish(_ data: MovieList) {
//publish
}
func add(_ observer: AnyObserver<MovieList>) {
observers.append(observer)
}
}
最后是关于 Observer
和 BookList
的 MovieList
协议。
protocol BookListObserver: Observer where ObservingType == BookList {}
protocol MovieListObserver: Observer where ObservingType == MovieList {}
对于我们最后的用例AViewController
:
class AViewController: UIViewController {
let bookListService = BookListService()
let movieListService = MovieListService()
override func viewDidLoad() {
super.viewDidLoad()
subscribe(toService: bookListService)
}
}
extension AViewController: BookListObserver {
func received(_ data: BookList) {
// booklist received
}
func subscribe(toService service: BookListService) {
service.add(AnyObserver(self))
}
}
到目前为止,没有任何错误。然而,在此之后,如果扩展 AViewController
符合 MovieListObserver
抛出
'MovieListObserver' requires the types 'BookList' and 'MovieList' be equivalent
extension AViewController: MovieListObserver {}
如果您需要进一步的更新,请告诉我。
更新:
我找到了 this topic,但无法以某种方式适用于我的情况。