这是一个RxSwift基本使用文章,具体的代码可以下载这个工程进行查看。RxSwiftLearn,示例代码来源于官方文档,自己只是在上边的学习项目中完善了一下代码,也可以直接去官网学习RxSwift中文文档
为什么选择RxSwift?
- 统一异步模型 :用
Observable替代回调地狱
- 线程安全 :通过
Scheduler明确线程调度
- 组合能力 :
zip, flatMap等操作符灵活组合任务
- 生命周期管理 :
DisposeBag自动清理资源
- 错误处理 :
catchError, retry优雅处理异常
1. 按钮点击事件处理
✅ 传统实现(Target-Action)
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(type: .system)
btn.setTitle("传统点击", for: .normal)
btn.frame = CGRect(x: 50, y: 100, width: 120, height: 40)
view.addSubview(btn)
btn.addTarget(self, action: #selector(handleTap), for: .touchUpInside)
}
@objc func handleTap() {
print("传统方式点击")
}
RxSwift实现
override func viewDidLoad() {
super.viewDidLoad()
let rxBtn = UIButton(type: .system)
rxBtn.setTitle("Rx点击", for: .normal)
rxBtn.backgroundColor = .systemBlue
rxBtn.frame = CGRect(x: 50, y: 200, width: 120, height: 40)
view.addSubview(rxBtn)
rxBtn.rx.tap
.subscribe(onNext: { [weak self] in
print("响应式点击")
})
.disposed(by: disposeBag)
}
核心类解析
| 类名 |
作用 |
使用场景 |
rx.tap |
扩展UIButton的点击事件流 |
替代addTarget |
subscribe |
订阅事件 |
处理点击逻辑 |
DisposeBag |
管理资源释放 |
防止内存泄漏 |
2. 滚动视图事件监听
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView()
scrollView.frame = CGRect(x: 0, y: 300, width: 300, height: 200)
scrollView.contentSize = CGSize(width: 300, height: 400)
view.addSubview(scrollView)
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("传统滚动位置: $scrollView.contentOffset.x)")
}
✅ RxSwift实现
override func viewDidLoad() {
super.viewDidLoad()
let scrollView = UIScrollView()
scrollView.frame = CGRect(x: 0, y: 300, width: 300, height: 200)
scrollView.contentSize = CGSize(width: 300, height: 400)
view.addSubview(scrollView)
scrollView.rx.contentOffset
.subscribe(onNext: { offset in
print("响应式滚动位置: $offset.x)")
})
.disposed(by: disposeBag)
}
🔍 核心类解析
| 类名 |
作用 |
使用场景 |
rx.contentOffset |
扩展UIScrollView的滚动事件流 |
替代scrollViewDidScroll |
BehaviorSubject |
保存最新偏移量 |
实时获取滚动位置 |
3. 网络请求链式调用
✅ 传统实现(回调嵌套)
override func viewDidLoad() {
super.viewDidLoad()
API.getToken { token in
API.getUserInfo(token: token) { user in
print("获取用户信息成功: $user.name)")
} failure: { error in
print("失败: $error)")
}
} failure: { error in
print("失败: $error)")
}
}
✅ RxSwift实现
override func viewDidLoad() {
super.viewDidLoad()
API.rx.getToken(username: "user", password: "123")
.flatMapLatest { token in
API.rx.getUserInfo(token: token)
}
.subscribe(
onNext: { user in
print("响应式获取用户: $user.name)")
},
onError: { error in
print("响应式错误: $error)")
}
)
.disposed(by: disposeBag)
}
核心类解析
| 类名 |
作用 |
使用场景 |
flatMapLatest |
扁平化嵌套请求 |
实现请求链式调用 |
Single |
单次结果封装 |
适配网络请求场景 |
4. 并发任务聚合
✅ 传统实现(串行请求)
override func viewDidLoad() {
super.viewDidLoad()
API.getTeacher(id: 1001) { teacher in
API.getComments(id: 1001) { comments in
print("教师: $teacher.name),评论数: $comments.count)")
}
}
}
✅ RxSwift实现
override func viewDidLoad() {
super.viewDidLoad()
Observable.zip(
API.rx.getTeacher(id: 1001),
API.rx.getComments(id: 1001)
)
.subscribe(
onNext: { teacher, comments in
print("教师: $teacher.name),评论数: $comments.count)")
}
)
.disposed(by: disposeBag)
}
🔍 核心类解析
| 类名 |
作用 |
使用场景 |
zip |
合并多个Observable |
并发请求聚合 |
Tuple |
存储组合结果 |
(Teacher, [Comment])类型 |
5. 冷热Observable对比
✅ 冷Observable(独立执行)
override func viewDidLoad() {
super.viewDidLoad()
let cold = Observable<Int>.create { observer in
observer.onNext(1)
return Disposables.create()
}
cold.subscribe { value in
print("冷Observable: $value)")
}
}
✅ 热Observable(共享事件)
override func viewDidLoad() {
super.viewDidLoad()
let hot = PublishSubject<Int>()
hot.onNext(2)
hot.subscribe { value in
print("热Observable: $value)")
}
}
🔍 核心类解析
| 类型 |
特点 |
使用场景 |
| 冷Observable |
每次订阅独立执行 |
网络请求、一次性任务 |
| 热Observable |
共享事件流 |
实时数据推送 |
6. 错误处理与重试机制
✅ RxSwift实现
override func viewDidLoad() {
super.viewDidLoad()
API.rx.login()
.retry(3) // 最多重试3次
.catchError { error in
print("最终错误: $error)")
return .just(User.default)
}
.subscribe { user in
print("登录用户: $user.name)")
}
.disposed(by: disposeBag)
}
🔍 核心类解析
| 类名 |
作用 |
使用场景 |
retry |
自动重试 |
网络不稳定时 |
catchError |
错误降级 |
返回默认值避免崩溃 |
7. UI状态管理
✅ 传统实现(直接赋值)
var isLoading = false {
didSet {
activityIndicator.isHidden = !isLoading
}
}
✅ RxSwift实现
let loadingState = BehaviorRelay<Bool>(value: false)
loadingState.asObservable()
.subscribe { isLoad in
activityIndicator.isHidden = !isLoad
}
.disposed(by: disposeBag)
🔍 核心类解析
| 类名 |
作用 |
使用场景 |
BehaviorRelay |
可变状态容器 |
管理加载状态 |
asObservable() |
转换为只读流 |
防止外部直接修改 |
所有核心类汇总表
| 类名 |
核心作用 |
典型使用场景 |
Observable |
异步事件流 |
网络请求、用户交互 |
Observer |
事件消费者 |
处理next/error/complete |
Disposable |
资源管理 |
取消订阅 |
Scheduler |
线程调度 |
主线程更新 |
Operator |
操作符 |
map, filter, zip等 |
Subject |
热Observable |
实时事件广播 |
Relay |
状态管理 |
BehaviorRelay, PublishRelay |
Driver |
安全绑定 |
UI绑定 |
Single |
单次结果 |
网络请求 |