ios - Rx swift : using rx_refreshing for uirefreshcontrol

标签 ios swift uirefreshcontrol rx-swift

我正在使用 UIRefreshControl + Variable 绑定(bind)来重新加载数据。

它正在工作,但是,以下内容对我来说是错误的:

1) 我知道 RXCocoa 扩展中有一个 rx_refreshing 变量,但我无法让它在这种情况下工作。

2) 我绑定(bind)了两次答案(这是数组的 Variable)。一次是在我加载 View Controller 时,一次是在 UIRefreshControl 刷新时。

3) 我检查 UIRefreshControl 是否正在刷新的部分看起来真的很尴尬。感觉违背了使用reactive的初衷?

...

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

...

最佳答案

所以首先,它实际上有效。它只是似乎在起作用。在您的代码中,您实际上并没有在调用 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.

关于ios - Rx swift : using rx_refreshing for uirefreshcontrol,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38578847/

相关文章:

ios - SceneKit Material 中充满了随机图案,为什么?

ios - 无法更改 UINavigationBar 颜色(快速)

ios - Objective C 为什么我需要在这种情况下进行类型转换?

ios - UIDocumentInteractionController() swift

ios - 如何使用动画进行刷新控制?

iphone - UIRefreshControl 无限期挂起

ios - YapDatabase 关系在重命名时不更新文件路径

ios - 当外部 scrollview 开始滚动时增加 tableview 高度

ios - SQLite Swift 绑定(bind)和检索

swift - 刷新时出现 fatal error : Array index out of range. Swift