[英]Swift how to conform to different associate type in a protocol
我正在开发一个 state 管理库。 最初的设计只有 1 个监听器,在我需要支持多个监听器之前效果很好。
原始设计在这里: Swift how to use generic protocol in generic class
这是我为支持多个听众所做的:
public protocol StateObserver: AnyObject {
associatedtype State
func didUpdateState(_ state: State)
}
public final class StateStore<Observer: StateObserver> {
struct WeakRef<T: AnyObject> {
weak var value: T?
}
public private(set) var state: Observer.State
private var observers = [WeakRef<Observer>]()
public init(initialState: Observer.State) {
state = initialState
}
public func addObservers(_ observers: [Observer]) {
self.observers += observers.map { WeakRef(value: $0) }
}
public func update(_ block: (inout Observer.State) -> Void) {
var nextState = state
block(&nextState)
state = nextState
notify()
}
public func notify() {
for observer in observers {
observer.value?.didUpdateState(state)
}
}
}
现在我需要用 2 个观察者创建商店:
class MyScene: SKScene {
init {
let leftPanel = LeftPanelSKNode()
let topBar = TopBarSKNode()
let store: StateStore<?> // How to make this support `LeftPanelSKNode `, `TopBarSKNode`, and `MyScene`?
store.addObservers([leftPanel, topBar, self])
}
现在我被困在这里。 我需要创建一个 StateStore<?> 的东西,它可以是MyScene
、 LeftPanelSKNode
和TopBarSKNode
。
首先,我不得不说您正在构建的内容已经存在于许多反应式库中:
Apple 组合中的CurrentValueSubject ;
RxSwift 中的BehaviorSubject ;
您还可以检查我自己制作的小型内部 class,它允许握住 state 并观察它ObservableProperty 。
回到您的问题,我找到了一种方法来逐个添加 StateObserver,同时只保留对它们的弱引用。
public protocol StateObserver: AnyObject {
associatedtype State
func didUpdateState(_ state: State)
}
class Node1: StateObserver {
typealias State = Int
func didUpdateState(_ state: Int) { }
}
class Node2: StateObserver {
typealias State = Int
func didUpdateState(_ state: Int) { }
}
class StateStore<StateType> {
private(set) var state: StateType
init(_ initialState: StateType) {
self.state = initialState
}
private var observers: [(StateType) -> Void] = []
func observe<Observer: StateObserver>(by observer: Observer) where Observer.State == StateType {
weak var weakObserver = observer
observers.append { state in
weakObserver?.didUpdateState(state)
}
}
func notify() {
observers.forEach {
$0(self.state)
}
}
}
let store = StateStore<Int>(0)
let node1 = Node1()
let node2 = Node2()
store.observe(by: node1)
store.observe(by: node2)
由于 StateObserver 中的关联类型,添加基于数组的观察 API 可能会出现问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.