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

时间:2019-03-14 14:21:33

标签: swift generics rx-swift

功能如下:

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

上下文:理想情况下,我有一个类,其中包含各种类型(字符串,整数等)的BehaviorRelay的集合。 Element通常代表这些类型,但这会带来两个问题:

  1. distinctUntilChanged坚持要闭包(例如:如果此方法返回了Driver<String>,那么简单地使用distinctUntilChanged()就可以满足要求,但是通用Element使其抱怨丢失关闭);
  2. onErrorJustReturn需要一个具体值,但是Element是通用的。

以下“解决方法”可能有效,但我怀疑有更好的解决方案

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

1 个答案:

答案 0 :(得分:1)

只要distinctUntilChanged()符合Element,就可以使用Equatable而不用闭包:

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())
}