这是一个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. 滚动视图事件监听
✅ 传统实现(UIScrollViewDelegate)
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)
.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 | 单次结果 | 网络请求 |