RxSwift:使用 rx_refreshing 进行 uirefreshcontrol
Posted
技术标签:
【中文标题】RxSwift:使用 rx_refreshing 进行 uirefreshcontrol【英文标题】:RxSwift: using rx_refreshing for uirefreshcontrol 【发布时间】:2016-07-25 23:22:24 【问题描述】:我正在使用UIRefreshControl
+ Variable
绑定重新加载数据。
它正在工作,但是,我觉得以下内容不对:
1) 我知道在 RXCocoa
扩展中有一个 rx_refreshing
变量,但我无法让它在这种情况下工作。
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】:首先,它没有真正起作用。它只是似乎在工作。在您的代码中,您实际上并没有在调用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.
【讨论】:
这太棒了——正是需要的那种非常实用、简单的sn-ps!关于您的上一个示例,我有几个问题:我将答案设置为变量,因此我可以在需要时轻松访问它的值。在您的情况下, answers 只是一个可观察的,它观察初始值(从不更改)和刷新,即值更改时。您不需要放置过滤器 $0 == false 以便仅在刷新值为 false 时刷新吗?其次,我看到你在那里做了什么 - 只有在 loadAnswer 完成时才会设置答案。 不需要filter
,因为rc.rx_controlEvent(.ValueChanged)
只会在刷新开始时发出一个事件。
您能否在示例中使用变量代替可观察的答案?
是的,它只是做你以前做的事情:使用bindTo
。您也不再需要shareReplayLatestWhileConnected
。不过我不认为有必要。以上是关于RxSwift:使用 rx_refreshing 进行 uirefreshcontrol的主要内容,如果未能解决你的问题,请参考以下文章
RxSwift : BehaviorRelay 代替变量使用