1. 为什么要使用 RxSwift?
我们先看一下 RxSwift 能够帮助我们做些什么:

Target Action

传统实现方法:
1
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
Copied!
1
func buttonTapped() {
2
print("button Tapped")
3
}
Copied!
通过 Rx 来实现:
1
button.rx.tap
2
.subscribe(onNext: {
3
print("button Tapped")
4
})
5
.disposed(by: disposeBag)
Copied!
你不需要使用 Target Action,这样使得代码逻辑清晰可见。

代理

传统实现方法:
1
class ViewController: UIViewController {
2
...
3
override func viewDidLoad() {
4
super.viewDidLoad()
5
scrollView.delegate = self
6
}
7
}
8
9
extension ViewController: UIScrollViewDelegate {
10
func scrollViewDidScroll(_ scrollView: UIScrollView) {
11
print("contentOffset: \(scrollView.contentOffset)")
12
}
13
}
Copied!
通过 Rx 来实现:
1
class ViewController: UIViewController {
2
...
3
override func viewDidLoad() {
4
super.viewDidLoad()
5
6
scrollView.rx.contentOffset
7
.subscribe(onNext: { contentOffset in
8
print("contentOffset: \(contentOffset)")
9
})
10
.disposed(by: disposeBag)
11
}
12
}
Copied!
你不需要书写代理的配置代码,就能获得想要的结果。

闭包回调

传统实现方法:
1
URLSession.shared.dataTask(with: URLRequest(url: url)) {
2
(data, response, error) in
3
guard error == nil else {
4
print("Data Task Error: \(error!)")
5
return
6
}
7
8
guard let data = data else {
9
print("Data Task Error: unknown")
10
return
11
}
12
13
print("Data Task Success with count: \(data.count)")
14
}.resume()
Copied!
通过 Rx 来实现:
1
URLSession.shared.rx.data(request: URLRequest(url: url))
2
.subscribe(onNext: { data in
3
print("Data Task Success with count: \(data.count)")
4
}, onError: { error in
5
print("Data Task Error: \(error)")
6
})
7
.disposed(by: disposeBag)
Copied!
回调也变得十分简单

通知

传统实现方法:
1
var ntfObserver: NSObjectProtocol!
2
3
override func viewDidLoad() {
4
super.viewDidLoad()
5
6
ntfObserver = NotificationCenter.default.addObserver(
7
forName: .UIApplicationWillEnterForeground,
8
object: nil, queue: nil) { (notification) in
9
print("Application Will Enter Foreground")
10
}
11
}
12
13
deinit {
14
NotificationCenter.default.removeObserver(ntfObserver)
15
}
Copied!
通过 Rx 来实现:
1
override func viewDidLoad() {
2
super.viewDidLoad()
3
4
NotificationCenter.default.rx
5
.notification(.UIApplicationWillEnterForeground)
6
.subscribe(onNext: { (notification) in
7
print("Application Will Enter Foreground")
8
})
9
.disposed(by: disposeBag)
10
}
Copied!
你不需要去管理观察者的生命周期,这样你就有更多精力去关注业务逻辑。

多个任务之间有依赖关系

例如,先通过用户名密码取得 Token 然后通过 Token 取得用户信息,
传统实现方法:
1
/// 用回调的方式封装接口
2
enum API {
3
4
/// 通过用户名密码取得一个 token
5
static func token(username: String, password: String,
6
success: (String) -> Void,
7
failure: (Error) -> Void) { ... }
8
9
/// 通过 token 取得用户信息
10
static func userinfo(token: String,
11
success: (UserInfo) -> Void,
12
failure: (Error) -> Void) { ... }
13
}
Copied!
1
/// 通过用户名和密码获取用户信息
2
API.token(username: "beeth0ven", password: "987654321",
3
success: { token in
4
API.userInfo(token: token,
5
success: { userInfo in
6
print("获取用户信息成功: \(userInfo)")
7
},
8
failure: { error in
9
print("获取用户信息失败: \(error)")
10
})
11
},
12
failure: { error in
13
print("获取用户信息失败: \(error)")
14
})
Copied!
通过 Rx 来实现:
1
/// 用 Rx 封装接口
2
enum API {
3
4
/// 通过用户名密码取得一个 token
5
static func token(username: String, password: String) -> Observable<String> { ... }
6
7
/// 通过 token 取得用户信息
8
static func userInfo(token: String) -> Observable<UserInfo> { ... }
9
}
Copied!
1
/// 通过用户名和密码获取用户信息
2
API.token(username: "beeth0ven", password: "987654321")
3
.flatMapLatest(API.userInfo)
4
.subscribe(onNext: { userInfo in
5
print("获取用户信息成功: \(userInfo)")
6
}, onError: { error in
7
print("获取用户信息失败: \(error)")
8
})
9
.disposed(by: disposeBag)
Copied!
这样你可以避免回调地狱,从而使得代码易读,易维护。

等待多个并发任务完成后处理结果

例如,需要将两个网络请求合并成一个,
通过 Rx 来实现:
1
/// 用 Rx 封装接口
2
enum API {
3
4
/// 取得老师的详细信息
5
static func teacher(teacherId: Int) -> Observable<Teacher> { ... }
6
7
/// 取得老师的评论
8
static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... }
9
}
Copied!
1
/// 同时取得老师信息和老师评论
2
Observable.zip(
3
API.teacher(teacherId: teacherId),
4
API.teacherComments(teacherId: teacherId)
5
).subscribe(onNext: { (teacher, comments) in
6
print("获取老师信息成功: \(teacher)")
7
print("获取老师评论成功: \(comments.count) 条")
8
}, onError: { error in
9
print("获取老师信息或评论失败: \(error)")
10
})
11
.disposed(by: disposeBag)
Copied!
这样你可用寥寥几行代码来完成相当复杂的异步操作。

那么为什么要使用 RxSwift ?

  • 复合 - Rx 就是复合的代名词
  • 复用 - 因为它易复合
  • 清晰 - 因为声明都是不可变更的
  • 易用 - 因为它抽象了异步编程,使我们统一了代码风格
  • 稳定 - 因为 Rx 是完全通过单元测试的
Last modified 9mo ago

文章作者: 张赛东
文章链接: https://zsd.name
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 张赛东 !
评论
 本篇
2022-04-19 张赛东
本篇 
2022-04-19 张赛东
  目录