为什么要使用 RxSwift ?

我们先看一下 RxSwift 能够帮助我们做些什么:


Target Action

传统实现方法:

1. button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
1. func buttonTapped() {
2. print("button Tapped")
3. }

通过 Rx 来实现:

1. button.rx.tap
2. .subscribe(onNext: {
3. print("button Tapped")
4. })
5. .disposed(by: disposeBag)

你不需要使用 Target Action,这样使得代码逻辑清晰可见。


代理

传统实现方法:

1. class ViewController: UIViewController {
2. ...
3. override func viewDidLoad() {
4. super.viewDidLoad()
5. scrollView.delegate = self
6. }
7. }

9. extension ViewController: UIScrollViewDelegate {
10. func scrollViewDidScroll(_ scrollView: UIScrollView) {
11. print("contentOffset: \(scrollView.contentOffset)")
12. }
13. }

通过 Rx 来实现:

1. class ViewController: UIViewController {
2. ...
3. override func viewDidLoad() {
4. super.viewDidLoad()

6. scrollView.rx.contentOffset
7. .subscribe(onNext: { contentOffset in
8. print("contentOffset: \(contentOffset)")
9. })
10. .disposed(by: disposeBag)
11. }
12. }

你不需要书写代理的配置代码,就能获得想要的结果。


闭包回调

传统实现方法:

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. }

8. guard let data = data else {
9. print("Data Task Error: unknown")
10. return
11. }

13. print("Data Task Success with count: \(data.count)")
14. }.resume()

通过 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)

回调也变得十分简单


通知

传统实现方法:

1. var ntfObserver: NSObjectProtocol!

3. override func viewDidLoad() {
4. super.viewDidLoad()

6. ntfObserver = NotificationCenter.default.addObserver(
7. forName: .UIApplicationWillEnterForeground,
8. object: nil, queue: nil) { (notification) in
9. print("Application Will Enter Foreground")
10. }
11. }

13. deinit {
14. NotificationCenter.default.removeObserver(ntfObserver)
15. }

通过 Rx 来实现:

1. override func viewDidLoad() {
2. super.viewDidLoad()

4. NotificationCenter.default.rx
5. .notification(.UIApplicationWillEnterForeground)
6. .subscribe(onNext: { (notification) in
7. print("Application Will Enter Foreground")
8. })
9. .disposed(by: disposeBag)
10. }

你不需要去管理观察者的生命周期,这样你就有更多精力去关注业务逻辑。


KVO

传统实现方法:

1. private var observerContext = 0

3. override func viewDidLoad() {
4. super.viewDidLoad()
5. user.addObserver(self, forKeyPath: #keyPath(User.name), options: [.new, .initial], context: &observerContext)
6. }

8. override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
9. if context == &observerContext {
10. let newValue = change?[.newKey] as? String
11. print("do something with newValue")
12. } else {
13. super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
14. }
15. }

17. deinit {
18. user.removeObserver(self, forKeyPath: #keyPath(User.name))
19. }

通过 Rx 来实现:

1. override func viewDidLoad() {
2. super.viewDidLoad()

4. user.rx.observe(String.self, #keyPath(User.name))
5. .subscribe(onNext: { newValue in
6. print("do something with newValue")
7. })
8. .disposed(by: disposeBag)
9. }

这样实现 KVO 的代码更清晰,更简洁并且更准确。


多个任务之间有依赖关系

例如,先通过用户名密码取得 Token 然后通过 Token 取得用户信息,

传统实现方法:

1. /// 用回调的方式封装接口
2. enum Api {

4. /// 通过用户名密码取得一个 token
5. static func token(username: String, password: String,
6. success: (String) -> Void,
7. failure: (Error) -> Void) { ... }

9. /// 通过 token 取得用户信息
10. static func userinfo(token: String,
11. success: (UserInfo) -> Void,
12. failure: (Error) -> Void) { ... }
13. }
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. })

通过 Rx 来实现:

1. /// 用 Rx 封装接口
2. enum Api {

4. /// 通过用户名密码取得一个 token
5. static func token(username: String, password: String) -> Observable<String> { ... }

7. /// 通过 token 取得用户信息
8. static func userInfo(token: String) -> Observable<UserInfo> { ... }
9. }
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)

这样你无需嵌套太多层,从而使得代码易读,易维护。


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

例如,需要将两个网络请求合并成一个,

通过 Rx 来实现:

1. /// 用 Rx 封装接口
2. enum Api {

4. /// 取得老师的详细信息
5. static func teacher(teacherId: Int) -> Observable<Teacher> { ... }

7. /// 取得老师的评论
8. static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... }
9. }
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)

这样你可用寥寥几行代码来完成相当复杂的异步操作。


那么为什么要使用 RxSwift ?

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