返回 导航

Swift

hangge.com

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 会触发重复执行操作。
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)

回到顶部