我如何用2个Swift协议制作一个观察者模式,其中两个关联类型必须是相同的?

问题描述 投票:1回答:1

我想使用 SE-0142(相关类型约束) 制作一个带有2个协议的观察者模式。IsObserverHasObservers (像服务器一样),那里有一个共享的 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)
    }
}

更新: 好吧,最后还是到了。比我想象的要难,需要进行类型擦除。在这个要领中,有两个版本:第一个版本是根据原问题的关联类型协议的版本。不过它是有限的--作为观察者的对象只能观察一种类型。所以我做了另一个变体,它可以有多个类型,但不使用associatetype协议,所以观察者必须手动检查类型。

https:/gist.github.comxaphod4f8a6402429759b6b3fd8ea2d8ea53c4。

swift protocols associated-types
1个回答
1
投票

我将简化一下你的用例(忽略观察),希望能让你明白这个概念。

HasObservers 基本上有2个相关的类型--------------------------------。DataTypeIsObserver 类型,然后你就会约束这个 IsObserver 型,才能有正确的 DataType

protocol IsObserver {
  associatedtype DataType
  func dataDidUpdate(_ data: [DataType])
}

protocol HasObservers {
  associatedtype DataType
  associatedtype ObserverType: IsObserver where ObserverType.DataType == DataType

  static func addObserver(_ observer: ObserverType)
  static func tellObserversDataDidUpdate(_ data: [DataType])

  // ..
}
© www.soinside.com 2019 - 2024. All rights reserved.