MJRefresh
是一個使用 Objective-C
編寫的刷新庫,使用簡單,功能強大。它既可以實現下拉刷新,也能實現上拉加載。本文通過樣例演示如何讓 RxSwift
與 MJRefresh
結合使用。
一、準備工作
1,配置 MJRefresh
關于 MJRefresh
的安裝配置和相關介紹,可以參考這篇文章:
2,對 MJRefresh 進行擴展
為了讓 MJRefresh
可以更好地與 RxSwift
配合使用,我這里對它進行擴展(MJRefresh+Rx.swift
),內容如下:
- 將下拉、上拉的刷新事件轉為
ControlEvent
類型的可觀察序列。 - 增加一個用于停止刷新的綁定屬性。
import RxSwift
import RxCocoa
//對MJRefreshComponent增加rx擴展
extension Reactive where Base: MJRefreshComponent {
//正在刷新事件
var refreshing: ControlEvent<Void> {
let source: Observable<Void> = Observable.create {
[weak control = self.base] observer in
if let control = control {
control.refreshingBlock = {
observer.on(.next(()))
}
}
return Disposables.create()
}
return ControlEvent(events: source)
}
//停止刷新
var endRefreshing: Binder<Bool> {
return Binder(base) { refresh, isEnd in
if isEnd {
refresh.endRefreshing()
}
}
}
}
3,網絡請求服務
這里專門封裝了一個網絡請求服務層(NetworkService.swift
),作用是當表格發生上拉、或下拉時,通過它獲取數據。為了方便演示,這里沒有真正去發起網絡請求,而是隨機生成 15 條數據,并延遲 1 秒返回。
import RxSwift
import RxCocoa
//網絡請求服務
class NetworkService {
//獲取隨機數據
func getRandomResult() -> Driver<[String]> {
print("正在請求數據......")
let items = (0 ..< 15).map {_ in
"隨機數據\(Int(arc4random()))"
}
let observable = Observable.just(items)
return observable
.delay(1, scheduler: MainScheduler.instance)
.asDriver(onErrorDriveWith: Driver.empty())
}
}
二、下拉刷新的樣例
1,效果圖
(1)頁面打開后自動會加載 15 條數據,并顯示在表格中。
(2)而每次下拉表格又會隨機生成 15 條新的數據,并替換表格里的原數據。
2,樣例代碼
(1)ViewModel.swift
主要是根據下拉刷新事件序列去查詢數據,同時數據返回后除了生成表格數據序列外,還有個停止刷新狀態的序列。
import RxSwift
import RxCocoa
class ViewModel {
//表格數據序列
let tableData:Driver<[String]>
//停止刷新狀態序列
let endHeaderRefreshing: Driver<Bool>
//ViewModel初始化(根據輸入實現對應的輸出)
init(headerRefresh: Driver<Void>) {
//網絡請求服務
let networkService = NetworkService()
//生成查詢結果序列
self.tableData = headerRefresh
.startWith(()) //初始化完畢時會自動加載一次數據
.flatMapLatest{ _ in networkService.getRandomResult() }
//生成停止刷新狀態序列
self.endHeaderRefreshing = self.tableData.map{ _ in true }
}
}
(2)ViewController.swift
ViewModel
初始化后,將表格數據序列綁定到 tableView
上顯示數據,同時將停止刷新序列綁定到 tableView
的 mj_header
上讓其自動停止刷新。
import UIKit
import RxSwift
import RxCocoa
class ViewController: UIViewController {
//表格
var tableView:UITableView!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
//創建表格視圖
self.tableView = UITableView(frame: self.view.frame, style:.plain)
//創建一個重用的單元格
self.tableView!.register(UITableViewCell.self,
forCellReuseIdentifier: "Cell")
self.view.addSubview(self.tableView!)
//設置頭部刷新控件
self.tableView.mj_header = MJRefreshNormalHeader()
//初始化ViewModel
let viewModel = ViewModel(headerRefresh:
self.tableView.mj_header.rx.refreshing.asDriver())
//單元格數據的綁定
viewModel.tableData.asDriver()
.drive(tableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "\(row+1)、\(element)"
return cell
}
.disposed(by: disposeBag)
//下拉刷新狀態結束的綁定
viewModel.endHeaderRefreshing
.drive(self.tableView.mj_header.rx.endRefreshing)
.disposed(by: disposeBag)
}
}