在 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
一般代表这些类型,但这会产生两个问题:
distinctUntilChanged
坚持要有一个闭包(例如:如果这个方法返回 Driver<String>
它会满足于简单地使用 distinctUntilChanged()
但通用的 Element
让它抱怨关于缺少闭包);
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())
}
函数如下:
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
一般代表这些类型,但这会产生两个问题:
distinctUntilChanged
坚持要有一个闭包(例如:如果这个方法返回Driver<String>
它会满足于简单地使用distinctUntilChanged()
但通用的Element
让它抱怨关于缺少闭包);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())
}