之前寫過兩篇RxSwift在UITableView中使用的文章,一篇是RXSwift在UITableView中的基本使用,另一篇是Moya + RXSwift + HandyJSONUITableView中的使用,有興趣的朋友可以看一下這兩篇文章
【RxSwift系列】RXSwift在UITableView中使用(一) http://www.lxweimin.com/p/4d9447d5278a
【RxSwift系列】Moya + RXSwift + HandyJSON在UITableView中的使用(二)http://www.lxweimin.com/p/fe36da1267cd
今天主要講的是用RxSwift基于MJRefresh在UITableView中實現下拉刷新,上拉加載,首先創建一個枚舉,設置刷新的幾種狀態
enum RefreshStatus: Int {
case InvalidData // 無效的數據
case DropDownSuccess // 下拉成功
case PullSuccessHasMoreData // 上拉,還有更多數據
case PullSuccessNoMoreData // 上拉,沒有更多數據
}
在viewModel中可以添加一個與刷新有關的變量
class BaseViewModel: NSObject {
let disposeBag = DisposeBag()
var refreshStatus = Variable(RefreshStatus.InvalidData)
var loadData = PublishSubject<Int>()
var dataSource = [SectionModel<String, BaseDataModel>]()
var result: Observable<[SectionModel<String, BaseDataModel>]>?
var page:Int = 1
}
refreshStatus是一個variable類型,它是一個泛型,它的.value屬性指向的就是它的實際參數類型。例子中,variable的實際參數類型是RefreshStatus,它是一個枚舉類型。variable類型的特點在于,只要改變value的值,就會發射改變后的數據,所以在viewModel里面改變refreshStatus的值,就可以響應刷新。
接下來在viewModel中實現請求的方法
override init() {
super.init()
//待錄入請求
result = loadData.flatMapLatest({ [weak self] (p) -> Observable<[SectionModel<String, BaseDataModel>]> in
return provider.request(.list(pageNumber: p)).map({ (x) -> [SectionModel<String, BaseDataModel>] in
guard let json = try? JSONSerialization.jsonObject(with: x.data, options: JSONSerialization.ReadingOptions(rawValue: 0)) as! [String: Any] else {
return [SectionModel(model: "", items: [])]
}
if let dic = json["data"] {
if p == 1 {
//處理返回的數據,給dataSource賦值
self?.refreshStatus.value = .DropDownSuccess
} else {
//處理返回的數據,給dataSource賦值
if array.count <= 0 {
self?.refreshStatus.value = .PullSuccessNoMoreData
} else {
self?.refreshStatus.value = .PullSuccessHasMoreData
}
}
return (self?.dataSource)!
} else {
if p != 1 {
self?.page -= 1
}
self?.refreshStatus.value = .InvalidData
}
return [SectionModel(model: "", items: [])]
}).catchErrorJustReturn([SectionModel(model: "", items: [])])
})
}
//MARK: 下拉刷新
func reloadData() {
page = 1
loadData.onNext(page)
}
//MARK: 上拉加載更多
func loadMoreData() {
page += 1
loadData.onNext(page)
}
然后在Controller中綁定數據請求
class BaseViewController: UIViewController {
var identifier = "identifier"
let disposeBag = DisposeBag()
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String,BaseDataModel>>()
let viewModel = BaseViewModel()
lazy var listTableView: UITableView = {
let listTableView = UITableView(frame: CGRect.zero, style: .plain)
listTableView.frame = CGRect(x: 0, y: 0, width: ScreenWidth, height: ScreenHeight)
listTableView.separatorStyle = .none
listTableView.rowHeight = 47
return listTableView
}()
override func viewDidLoad() {
super.viewDidLoad()
mainView.addSubview(listTableView)
listTableView.register(BaseTableViewCell.self, forCellReuseIdentifier: identifier)
listTableView.mj_header = MJRefreshStateHeader(refreshingBlock: {
self.viewModel.reloadData()
})
listTableView.mj_footer = MJRefreshBackNormalFooter(refreshingBlock: {
self.viewModel.loadMoreData()
})
dataSource.configureCell = {
_, tableView, indexPath, model in
let cell = tableView.dequeueReusableCell(withIdentifier: self.identifier, for: indexPath) as! BaseTableViewCell
return cell
}
//數據綁定
viewModel.result?
.bind(to: listTableView.rx.items(dataSource: dataSource))
.addDisposableTo(disposeBag)
//改變刷新狀態
viewModel.refreshStatus.asObservable().subscribe(onNext: { (status) in
self.refreshStatus(status: status,tableView: self.listTableView)
}).addDisposableTo(disposeBag)
listTableView.mj_header.beginRefreshing()
//cell點擊事件
listTableView.rx.modelSelected(SystemMessgeDataModel.self).subscribe(onNext: { (model) in
})
.addDisposableTo(disposeBag)
}
/**
設置刷新狀態
*/
func refreshStatus(status:RefreshStatus,tableView: UITableView) {
switch status {
case .InvalidData: // 無效的數據
tableView.mj_header.endRefreshing()
tableView.mj_footer.endRefreshing()
return
case .DropDownSuccess: // 下拉成功
tableView.mj_header.endRefreshing()
tableView.mj_footer.resetNoMoreData()
case .PullSuccessHasMoreData: // 上拉,還有更多數據
tableView.mj_footer.endRefreshing()
case .PullSuccessNoMoreData: // 上拉,沒有更多數據
tableView.mj_footer.endRefreshingWithNoMoreData()
}
tableView.mj_header.endRefreshing()
}
}