RxSwift|RxSwift 入门练习总结
demo.gif 使用的第三方库
target 'WeatherDemo_RxSwift' douse_frameworks!pod 'RxSwift', '~> 3.5.0'
pod 'RxCocoa', '~> 3.5.0'
pod 'RxDataSources', '~> 1.0.4'end
1.所有的控制器都加上析构函数,以方便查看是否有循环引用
deinit {
print("\(self) 释放")
}
2.按钮订阅点击事件
tapButton.rx.tap
.subscribe({ [unowned self] _ in
let numStr : String = self.numberLabel.text!
let number = Int(numStr)
self.numberLabel.text = String(number! + 1)}).addDisposableTo(disposeBag)
注意: 一定要加[unowned self],或者[weak self]否则会出现循环引用,关于它俩的使用情况,参考
@ONEVCAT
内存管理,WEAK 和 UNOWNED3.订阅手势事件,给按钮添加长按手势
let longPressGesture = UILongPressGestureRecognizer()
longPressGesture.rx.event
.subscribe(onNext: { [unowned self] _ inlet numStr : String = self.numberLabel.text!
let number = Int(numStr)
self.numberLabel.text = String(number! + 1)}).addDisposableTo(disposeBag)
self.tapButton.addGestureRecognizer(longPressGesture)
此处,用了subscribe.onNext.注意:onNext 只监听sequence发出的next事件中的element进行处理,他会忽略error和completed事件
疑问点:大部分情况subscribe 硬敲出来的 为啥代码没有自动补全??? 4.结合tableView,Variable使用示例
// Variable流,初始值字符串数组
let items = Variable(["Mike",
"Apples",
"Ham",
"Eggs"])let items2 = [
"Fish",
"Carrots",
"Mike",
"Apples",
"Ham",
"Eggs",
"Bread",
"Chiken",
"Water"
]// Variable使用必须要加asObservable
// 数据流绑定到tableView
items.asObservable()
.bind(to: tableView.rx.items(cellIdentifier: "Cell",cellType:UITableViewCell.self),curriedArgument: { (row, element, cell) in
cell.textLabel?.text = element
}).addDisposableTo(disposeBag)// 原生的refresh
refreshControl.rx.controlEvent(.valueChanged)
.subscribe(onNext: { [unowned self] _ in
// 更改Variable.value 模拟刷新
items.value = https://www.it610.com/article/items2
self.refreshControl.endRefreshing()
}).addDisposableTo(disposeBag)tableView.addSubview(refreshControl)
知识点:
- 要理解Variable,需要先理解Subject,Subjet是observable和Observer之间的桥梁,一个Subject既是一个Obserable也是一个Observer,他既可以发出事件,也可以监听事件
- BehaviorSubject : 当你订阅了BehaviorSubject,你会接受到订阅之前的最后一个事件
- Variable是BehaviorSubject一个包装箱,就像是一个箱子一样,使用的时候需要调用asObservable()拆箱,里面的value是一个BehaviorSubject,他不会发出error事件,但是会自动发出completed事件
// 代理声明 必须要继承 class 否则报错
protocol DataEnteredDelegate: class {
func userDidEnterInformation( info: String )
}// 代理声明必须要weak,防止循环引用
weak var delegate : DataEnteredDelegate? = nil// 监听键盘右下角done事件,调用代理方法
@IBAction func textOnExit(_ sender: Any) {
delegate?.userDidEnterInformation(info: textField.text!)
self.navigationController?.popViewController(animated: true)
}
知识点:
- 需要把protocol 限制在 class 内,这是因为 Swift 的 protocol 是可以被除了 class 以外的其他类型遵守的, 而对于像 struct 或是 enum 这样的类型,本身就不通过引用计数来管理内存,所以也不可能用 weak 这样的 ARC 的概念来进行修饰
王巍 (@ONEVCAT) delegate
// 1.数据流 just用法
let items = Observable.just([
SectionModel(model: "B",items:[
"Barbara Cole",
"Barbara Cooper",
"Barbara Diaz",
"Barbara Edwards",
"Barbara Garcia",
"Barbara Gray",
"Barbara Griffin",
"Barbara Hill",
"Barbara Howard",
"Barbara Hughes"
]),
SectionModel(model:"C",items:[
"Carol Lopez", "Carol Lopez"
]),
SectionModel(model: "E", items: [
"Elizabeth Jenkins", "Elizabeth Kelly"
]),
SectionModel(model: "H", items: ["Helen Anderson", "Helen Bailey", "Helen Cole", "Helen Cox"]),
SectionModel(model: "J", items: ["James Anderson", "James Barnes", "James Bell"]),
SectionModel(model: "K", items: ["Karen Green", "Karen Jenkins", "Karen Jones", "Karen Jordan"]),
SectionModel(model: "L", items: ["Linda Taylor", "Linda Taylor", "Linda Torres", "Linda West", "Lisa Brooks"]),
SectionModel(model: "M", items: ["Margaret Bell", "Margaret Coleman", "Margaret Cox", "Margaret Foster"]),
SectionModel(model: "R", items: ["Robert Clark", "Robert Coleman", "Robert Cook", "Robert Cook"]),
SectionModel(model: "S", items: ["Susan Fisher", "Susan Ford", "Susan Ford", "Susan Hernandez", "Susan Howard"]),
])// 2.创建数据源 类型
let dataSource = RxTableViewSectionedReloadDataSource>()// 3. dataSources配置cell
fileprivate func setupDataSource() {// 参数必须4个,_占位用
dataSource.configureCell ={ (_,tableView,IndexPath,element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = element
return cell
}// 监听右侧边缘小字母点击事件
dataSource.sectionForSectionIndexTitle = { (dataSource,title,index) -> Int in
print("\(index)")
return index
}dataSource.sectionIndexTitles = { data -> [String]? in
return data.sectionModels.map{ $0.model }
}
}//4. 数据流items,绑定到dataSource上
items.bind(to: tableView.rx.items(dataSource: dataSource))// 5. 设置tableView代理
_ = tableView.rx.setDelegate(self)
7. 自定义可观察序列create 示例
//create 自定义可观察序列 返回的WeatherData 类型流
func fetchWeatherData() -> Observable {
let observable = Observable.create { [weak self] observer in
if let weakSelf = self{
let time = 0.5 + TimeInterval(arc4random_uniform(10)) / 10.0// 主线程延迟处理,模拟网络请求数据
DispatchQueue.main.asyncAfter(deadline: .now() + time, execute: {
let shouldFail = arc4random_uniform(2) == 0
if shouldFail {
observer.onError(NSError(domain:"Fake network error", code: 0, userInfo: nil))
}else{
observer.onNext(weakSelf.createRandomWeatherData())
observer.onCompleted()
}})
}
return Disposables.create() // 固定写法,记住 需实现.onError() .onNext .onCompleted
}
return observable.shareReplay(1)
}
// 建议使用addDisposableTo
self.viewModel.locationName.drive(self.locationLabel.rx.text).addDisposableTo(disposeBag)// 而不是用 disposed(by: disposeBag)
self.viewModel.locationName.drive(self.locationLabel.rx.text).disposed(by: disposeBag)// 按钮tap事件建议使用subscribe
button.rx.tap
.subscribe(onNext:{
[unowned self] in
let selectedDate = dateFormatter.string(from: self.datePicker.date)
self.title = selectedDate
}).addDisposableTo(disposeBag)// 而不是用bind
button.rx.tap
.bind { [unowned self] in
let selectedDate = dateFormatter.string(from: self.datePicker.date)
self.title = selectedDate
}.addDisposableTo(disposeBag)
【RxSwift|RxSwift 入门练习总结】RxSwift概念理解
RxSwift学习资料,内涵很多RxSwift开源项目
本示例下载
推荐阅读
- 源程序|SpringBoot框架入门(二)
- 借问变量何处存,牧童笑称用指针,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang指针的使用EP05
- 兼容并蓄广纳百川,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang复合容器类型的声明和使用EP04
- 分门别类输入输出,Go lang1.18入门精炼教程,由白丁入鸿儒,go lang基本数据类型和输入输出EP03
- TS入门基础
- 编程基础教程
- Steemit上练习书法赚钱194弹——并|Steemit上练习书法赚钱194弹——并|欢迎围观参与
- 微服务系列|微服务系列(分布式文件存储之 MinIO 入门指南)
- Reactive|Reactive UI -- 反应式编程UI框架入门学习(一)
- Java开发学习(二十三)----SpringMVC入门案例、工作流程解析及设置bean加载控制