Das Problem, das Sie haben, ist, weil der Operator RxSwift buffer
nicht wie der Operator RxJS buffer
funktioniert. Es funktioniert mehr wie der RxJS bufferWithTimeOrCount
Operator.
Derzeit gibt es ab Version 3.4.0 keine Entsprechung zum Operator buffer
. Es wäre etwas wie func buffer(_ boundary: Observer<BoundaryType>) -> Observable<[E]>
Das war eine lustige Frage zu beantworten. Am Ende habe ich einen Pufferoperator erstellt, den ich am Ende dieser Antwort zur Verfügung stelle. Hier ist, wie ich würde die Lösung schreiben, dass in Andre Code definiert:
let trigger = button.rx.tap.debounce(0.25, scheduler: MainScheduler.instance)
let clickStream = button.rx.tap.asObservable()
.buffer(trigger)
.map { $0.count }
.map { $0 == 1 ? "click" : "\($0)x clicks" }
let clearStream = clickStream
.debounce(10.0, scheduler: MainScheduler.instance)
.map { _ in "" }
Observable.merge([clickStream, clearStream])
.bind(to: label.rx.text)
.disposed(by: bag)
Der obige Code sollte im View-Controller des viewDidLoad
Methode platziert werden. Es gibt eine große Veränderung und eine kleine Veränderung, die ich gemacht habe. Die kleine Änderung ist, dass ich Entprellen anstelle von Drossel verwendet habe. Auch hier denke ich, dass RxJs Gas anders funktioniert als RxSwifts Gas. Die große Veränderung ist, dass ich seinen multiClickStream und singleClickStream kombiniert habe. Ich bin nicht ganz sicher, warum er zwei getrennte Ströme machte ...
Eine andere Änderung, die ich machte, war, alle Observables, die das Etikett beeinflussen, in eine Observable zu rollen, an die das Etikett binden könnte, anstatt andere zu haben. Ich denke, das ist sauberer.
Unten ist der Puffer-Operator, den ich definiert habe.
extension Observable {
/// collects elements from the source sequence until the boundary sequence fires. Then it emits the elements as an array and begins collecting again.
func buffer<U>(_ boundary: Observable<U>) -> Observable<[E]> {
return Observable<[E]>.create { observer in
var buffer: [E] = []
let lock = NSRecursiveLock()
let boundaryDisposable = boundary.subscribe { event in
lock.lock(); defer { lock.unlock() }
switch event {
case .next:
observer.onNext(buffer)
buffer = []
default:
break
}
}
let disposable = self.subscribe { event in
lock.lock(); defer { lock.unlock() }
switch event {
case .next(let element):
buffer.append(element)
case .completed:
observer.onNext(buffer)
observer.onCompleted()
case .error(let error):
observer.onError(error)
buffer = []
}
}
return Disposables.create([disposable, boundaryDisposable])
}
}
}
Vielen Dank für die Antwort. Ich lasse die Frage ein wenig mehr hängen, für den Fall, dass jemand mit einer Lösung kommt oder ich selbst etwas herausgefunden habe. –
Sie könnten diese Diskussion interessant finden: https://github.com/ReactiveX/RxSwift/issues/590 –
Vielen Dank für die Lösung und die Erklärung. –