繁体   English   中英

Swift 如何在协议中符合不同的关联类型

[英]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<?> 的东西,它可以是MySceneLeftPanelSKNodeTopBarSKNode

首先,我不得不说您正在构建的内容已经存在于许多反应式库中:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM