Swift - RxSwift的使用详解67(重复执行某个操作序列:repeatWhen)
作者:hangge | 2018-06-15 08:10
有时我们的程序需要重复执行某些操作,比如数据的刷新(发送一个网络请求后,点击刷新按钮便能继续发送这个网络请求):

之前我也写过文章演示了如何实现类似的功能(点击查看)。下面介绍另一种更简单的方法,通自定义的操作符实现序列的重复执行。
一、扩展 ObservableConvertibleType
(1)为保证通用性,我们首先对 ObservableConvertibleType 进行扩展,增加一个 repeatWhen 的方法。
(2)该方法还会监视另一个序列,这里我称其为 notifier。当 notifier 发出新事件时,会将原始序列再次发出。从而实现源序列的重复执行。
extension ObservableConvertibleType {
//当被监视的序列(notifier)发出事件时,重新发送源序列
func repeatWhen<O: ObservableType>(_ notifier: O) -> Observable<E> {
return notifier.map { _ in }
.startWith(())
.flatMap { () -> Observable<E> in
self.asObservable()
}
}
}
二、使用样例
1,使用简单的序列进行测试
(1)我们对一个会发送三个元素事件的序列进行订阅,并将结果打印到控制台中。同时该序列通过 repeatWhen 操作符监视另一个 notifier 序列,该 notifier 会触发重复执行操作。
(2)运行结果如下,可以看到算上 notifier 触发的两次重复执行操作,源序列一共订阅执行了 3 次。
let disposeBag = DisposeBag()
//触发序列
let notifier = PublishSubject<()>()
//对源序列进行订阅
Observable.of("a", "b", "!")
.repeatWhen(notifier) //设置触发重复执行行为的监视序列
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
//重复两次
notifier.onNext(())
notifier.onNext(())
(2)运行结果如下,可以看到算上 notifier 触发的两次重复执行操作,源序列一共订阅执行了 3 次。
2,重复请求数据样例
(1)效果图
- 我们使用 URLSession 去发起网络请求,随机获取一首歌曲信息,并将结果弹出显示。
- 除了程序启动后会自动请求一次外,点击“刷新”按钮也可再次请求。

(2)样例代码
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class ViewController: UIViewController {
//刷新按钮
@IBOutlet weak var refreshButton: UIBarButtonItem!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//创建URL对象
let urlString = "http://douban.fm/j/mine/playlist?type=n&channel=1&from=mainsite"
let url = URL(string:urlString)
//创建请求对象
let request = URLRequest(url: url!)
//创建并发起请求
URLSession.shared.rx.data(request: request)
.repeatWhen(refreshButton.rx.tap) //刷新按钮点击后再次请求
.subscribe(onNext: {
data in
let json = try! JSONSerialization.jsonObject(with: data,
options: JSONSerialization.ReadingOptions.mutableContainers)
as! [String: Any]
let song = (json["song"] as! [[String: Any]])[0]
let artist = song["artist"] as! String
let title = song["title"] as! String
self.showAlert(message: artist, title: title)
}).disposed(by: disposeBag)
}
//显示提示信息
func showAlert(message: String, title: String) {
let alert = UIAlertController(title: title, message: message,
preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "确定", style: .cancel))
self.present(alert, animated: true)
}
}
全部评论(0)