RxSwift:使用rx_refreshing进行uirefreshcontrol

时间:2016-07-25 23:22:24

标签: ios swift uirefreshcontrol rx-swift

我使用UIRefreshControl + Variable绑定来重新加载数据。

然而,这是有效的,以下对我来说感觉不对:

1)我知道rx_refreshing扩展程序中有一个RXCocoa变量,但我无法在此上下文中使用它。

2)我绑定答案(数组的Variable)两次。一旦我加载视图控制器,并在UIRefreshControl刷新时再次加载。

3)我检查UIRefreshControl是否令人耳目一新的部分看起来很尴尬。感觉它是否违背了使用反应的目的?

...

let answers: Variable<[Answer]> = Variable([])

override func viewDidLoad() {       
  loadAnswers()
     .shareReplay(1)
     .bindTo(answers)
     .addDisposableTo(self.disposeBag)
  setupRx()
}

func loadAnswers() -> Observable<[Answer]> {
  return Network.rxArrayRequest(Spark.Answers)
}  

func setupRx() {
  rc.rx_controlEvent(.ValueChanged)
    .map { _ in !self.rc.refreshing }
    .filter { $0 == false }
    .flatMapLatest { [unowned self] _ in
      return self.loadAnswers()
    }
    .bindTo(answers)
    .addDisposableTo(self.disposeBag)

  rc.rx_controlEvent(.ValueChanged)
    .map { _ in self.rc.refreshing }
    .filter { $0 == true }
    .subscribeNext { [unowned self] _ in
      self.rc.endRefreshing()
    }
    .addDisposableTo(self.disposeBag)
}

...

1 个答案:

答案 0 :(得分:13)

首先,它的实际上正在运作。只是似乎才能正常工作。在您的代码中,在致电rc.endRefreshing()之前,您实际上并没有等待网络请求完成。相反,您只是拨打网络电话,然后立即拨打endRefreshing()

// `rc.rx_controlEvent(.ValueChanged)` only gets called once,
// when the user pulls down.

rc.rx_controlEvent(.ValueChanged)       // user pulled down to refresh
  .map { _ in !self.rc.refreshing }     // !true -> false 
  .filter { $0 == false }               // false == false
  .flatMapLatest { [unowned self] _ in
    return self.loadAnswers()           // request answers
  }
  .bindTo(answers)
  .addDisposableTo(self.disposeBag)

rc.rx_controlEvent(.ValueChanged)       // user pulled down to refresh
  .map { _ in self.rc.refreshing }      // true -> true
  .filter { $0 == true }                // true == true
  .subscribeNext { [unowned self] _ in
    self.rc.endRefreshing()             // end refreshing
  }
  .addDisposableTo(self.disposeBag)

要解决问题1,您是对的,您可以使用rx_refreshing关闭刷新而不是endRefreshing()

要解决问题2,我不认为Variable是必要的或有用的,至少在本例中。你仍然可以使用它。此外,在两个地方loadAnswers()没有必要。

要解决问题3,是的,您可以简化这一点并使用Rx更多。

以下代码实际可行,使用rx_refreshing,并简化了很多事情:

let initial = Observable<Void>.just(())
let refresh = rc.rx_controlEvent(.ValueChanged).map { _ in () }
let answers = Observable.of(initial, refresh)
    .merge()
    .flatMapLatest{ _ in self.loadAnswers() }
    .shareReplayLatestWhileConnected()

answers
    .map { _ in false }
    .bindTo(rc.rx_refreshing)
    .addDisposableTo(disposeBag)

// also use `answers` to bind to your data source, etc.