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)