2017-04-07 9 views
0

我正在嘗試重新創建一個代碼片段,該代碼片段基本上統計一個按鈕在一行中被單擊的次數。代碼是在RxJS中,我試圖將它轉換爲RxSwift用於學習目的,但是可以找出緩衝區和節流部分。RxSwift - 如何節制緩衝區的時間跨度

You can see the js code on jsfiddle

目前我有這個

tapButton.rx.tap  
    .buffer(timeSpan: 0.25, count: 10, scheduler: MainScheduler.instance) 
    .map {$0.count} 
    .filter { $0 >= 2 } 
    .subscribe(onNext: { events in 
    print(events) 
    }).addDisposableTo(disposeBag) 

而且我想不通我怎麼能延遲,直到攻兩端並收集所有的值,因爲像RxJS示例中的最後發射。

回答

2

您遇到的問題是因爲RxSwift buffer操作員不像RxJS buffer操作員那樣工作。它更像RxJS bufferWithTimeOrCount運營商。

目前,從版本3.4.0開始,沒有等效於buffer運算符。它的簽名會像func buffer(_ boundary: Observer<BoundaryType>) -> Observable<[E]>

這是一個有趣的問題來回答。我最終在這個答案的底部提供了一個緩衝區操作符。這裏是出了在Andre的代碼I的定義將如何寫溶液:

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) 

上述代碼應放置在視圖控制器的viewDidLoad方法。我做了一個大的改變和一個小的改變。這個小小的變化是我用反彈而不是油門。再一次,我認爲RxJS的油門與RxSwift的油門不同。最大的改變是我將multiClickStream和singleClickStream結合起來。我不完全確定他爲什麼做了兩個獨立的流...

我做的另一個改變是將影響標籤的所有可觀察物捲成標籤可以綁定的一個可觀察物,而不是具有不同的可觀察物。我認爲這更清潔。

下面是我定義的緩衝區操作符。

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]) 
     } 
    } 
} 
+0

謝謝你的回答。如果有人提供解決方案,或者我自己想出了一些解決方案,我會讓這個問題多一點。 –

+1

您可能會覺得這個討論很有趣:https://github.com/ReactiveX/RxSwift/issues/590 –

+0

非常感謝您的解決方案和解釋。 –