在 RxSwift getter 函数中使用 Swift 泛型 - 各种问题

Using Swift generics in a RxSwift getter function - various problems

函数如下:

func registerFor<Element>(relayId id: String) -> Driver<Element>? {
    guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
    return relay.asObservable()
        .distinctUntilChanged { a, b in
            return a != b
        }.flatMapLatest { value in
            return Observable.create { observer in
                observer.on(.next(value))
                return Disposables.create()
            }
        }.asDriver(onErrorJustReturn: Element())
}

distinctUntilChanged 行抛出以下错误:

Contextual closure type '(Element) throws -> _' expects 1 argument, 
but 2 were used in closure body

asDriver 行抛出以下错误(当然):

Non-nominal type 'Element' does not support explicit initialization

上下文:我有一个 class,理想情况下有一个 BehaviorRelay 各种类型(字符串、整数等)的集合。 Element 一般代表这些类型,但这会产生两个问题:

  1. distinctUntilChanged 坚持要有一个闭包(例如:如果这个方法返回 Driver<String> 它会满足于简单地使用 distinctUntilChanged() 但通用的 Element 让它抱怨关于缺少闭包);
  2. onErrorJustReturn 需要具体值,但 Element 是通用值。

以下 "workaround" 可能有效,但我怀疑有更好的解决方案

protocol Inii {
    init()
}

func registerFor(relayId id: String, def: Inii.Type) -> Driver<Inii>? {
    return relays[id]?.asObservable()
        .distinctUntilChanged { _, _ in
            return true
        }.flatMapLatest { value in
            return Observable.create { observer in
                observer.on(.next(value))
                return Disposables.create()
            }
        }.asDriver(onErrorJustReturn: def.init())
}

尽管我仍然不确定要在 distinctUntilChanged 闭包中放入什么。


附录 A

我认为如果要为非泛型类型实现 distinctUntilChanged 闭包,则需要以下内容:

.distinctUntilChanged { previousValue, currentValue in
    return previousValue == currentValue
}

但是,当与通用 Element 一起使用时,仍然会抛出以下错误:

Contextual closure type '(Inii) throws -> _' expects 1 argument, 
but 2 were used in closure body

附录 B

这是另一种方法,但问题略有不同:

protocol Inii {
    init()
}

var relay = BehaviorRelay<String>(value: "")

func registerFor<Element>(def: Element.Type) -> Driver<Element> where Element: Inii {
    return relay.asObservable()
        .distinctUntilChanged { previousValue, currentValue in
            return previousValue == currentValue
        }.flatMapLatest { value in
            return Observable.create { observer in
                observer.on(.next(value))
                return Disposables.create()
            }
        }.asDriver(onErrorJustReturn: def.init())
}

这种情况下的错误是:

Member 'next' in 'Event<_>' produces result of type 'Event<Element>', 
but context expects 'Event<_>'

observer.on

只要 Element 符合 Equatable:

就可以不用闭包使用 distinctUntilChanged()
protocol EmptyInit {
    init()
}

func registerFor<Element>(relayId id: String) -> Driver<Element>? where Element: Equatable, Element: EmptyInit {
    guard let relay = relays[id] as? BehaviorRelay<Element> else { return nil }
    return relay.asObservable()
        .distinctUntilChanged()
        .flatMapLatest { value in
            return Observable.create { observer in
                observer.on(.next(value))
                return Disposables.create()
            }
        }.asDriver(onErrorJustReturn: Element())
}