此篇文章旨在说明如何使用RXSwfit框架进行一个异步的网络请求,并让tableView订阅该网络请求的返回数据进行显示或者提示错误。
·需求
· 点击右上角的刷新按钮获取数据
获取成功:将获取到的数据显示在TableView上
获取失败:什么都不做
· 优化用户连续点击,请求发送以及页面刷新过于频繁的情况
· 点击左上角的停止按钮,将停止当前的网络请求
·导入框架
如果需要现实复杂的TableView(比如对表内数据分多个Section显示)建议导入RxDataSources类,这样会使代码看起来简洁很多
如果本地的pod索引文件长时间没有更新,可能会导致pod install失败,只要pod repo update后再pod install即可
# Podfile
use_frameworks!
target 'RXDemo' do
pod 'RxSwift', '~> 5.0.0'
pod 'RxCocoa', '~> 5.0.0'
pod 'RxDataSources', '~> 4.0'
end
·样例
import UIKit
import RxSwift
import RxCocoa
import RxDataSources
class ViewController: UIViewController {
let bag = DisposeBag()
@IBOutlet weak var rightItem: UIBarButtonItem!
@IBOutlet weak var leftItem: UIBarButtonItem!
@IBOutlet weak var tableView: UITableView!
let requestStopped = BehaviorRelay.init(value: false)
override func viewDidLoad() {
super.viewDidLoad()
let tapOb = rightItem.rx.tap.asDriver() // 将序列转化为Driver(Driver不接收error事件,并且回调会在主线程进行)
.throttle(DispatchTimeInterval.seconds(1), latest: true) // 为防止重复请求 1秒内连续点击,只识别最后一次点击
.startWith(())// 第一次进入app 调用一次点击 获取数据
.map({"我要搜索xxx"}) // 假数据,假设这个是请求参数
.flatMapLatest { str in // 为防止重复请求 flatMapLatest的作用在于多次点击发送请求,只有最后一个请求(Observable<[SectionModel<String,String>])才会被订阅的对象执行相关回调
return self.getData(str).asDriver(onErrorJustReturn: []) // 这个observable会返回请求的数据,tableView订阅它可以获得请求数据进行显示处理
}
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.rowHeight = 44
let dataSource = RxTableViewSectionedReloadDataSource<SectionModel<String,String>>(configureCell: { (dataSource,tv,indexPath,ele) in
print("配置Cell线程:",Thread.current)
let cell = tv.dequeueReusableCell(withIdentifier: "cell")!
cell.textLabel?.text = ele
return cell
})
dataSource.titleForHeaderInSection = { ds , index in
return ds.sectionModels[index].model
}
tapOb.drive(tableView.rx.items(dataSource: dataSource)).disposed(by: bag)//.bind(to: tableView.rx.items(dataSource: dataSource)).disposed(by: bag)
}
func getData(_ keyWord:String) -> Observable<[SectionModel<String,String>]>{
print("请求数据参数为:",keyWord)
// 创建一个序列 被订阅后将请求数据
let res = Observable<[SectionModel<String,String>]>.create { (oob) -> Disposable in
self.delay(3) {
print("获取数据线程:",Thread.current)
if arc4random() % 2 == 0 {
print("发生错误!")
}else{
print("正常请求到数据了")
oob.onNext([SectionModel.init(model: "", items: ["1","2"])])
}
}
return Disposables.create()
}.takeUntil(self.leftItem.rx.tap)// 如果self.leftItem发出tap信号,那么将订阅者将终止对这个序列的监听
return res
}
///延迟执行
/// - Parameters:
/// - delay: 延迟时间(秒)
/// - closure: 延迟执行的闭包
public func delay(_ delay: Double, closure: @escaping () -> Void) {
DispatchQueue.global().asyncAfter(deadline: .now() + delay) {
closure()
}
}
deinit {
print("销毁了")
}
}