本专栏基于 Swift 言语,对响应式、函数式编程的闻名结构 RxSwift 进行了核心流程分析和代码实战演示。

本文经过比照iOS开发中常用的完成办法展现了RxSwift的结构魅力。

传统完成与 RxSwift 比照

Target Action

传统完成办法:

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

经过 Rx 来完成:

button.rx.tap
    .subscribe(onNext: {
        print("button Tapped")
    })
    .disposed(by: disposeBag)

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

署理

传统完成办法:

class ViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.delegate = self
    }
}
extension ViewController: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        print("contentOffset: (scrollView.contentOffset)")
    }
}

经过 Rx 来完成:

class ViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()
        scrollView.rx.contentOffset
            .subscribe(onNext: { contentOffset in
                print("contentOffset: (contentOffset)")
            })
            .disposed(by: disposeBag)
    }
}

你不需要书写署理的装备代码,就能获得想要的结果。

闭包回调

传统完成办法:

URLSession.shared.dataTask(with: URLRequest(url: url)) {
    (data, response, error) in
    guard error == nil else {
        print("Data Task Error: (error!)")
        return
    }
    guard let data = data else {
        print("Data Task Error: unknown")
        return
    }
    print("Data Task Success with count: (data.count)")
}.resume()

经过 Rx 来完成:

URLSession.shared.rx.data(request: URLRequest(url: url))
    .subscribe(onNext: { data in
        print("Data Task Success with count: (data.count)")
    }, onError: { error in
        print("Data Task Error: (error)")
    })
    .disposed(by: disposeBag)

回调也变得十分简单。

通知

传统完成办法:

var ntfObserver: NSObjectProtocol!
override func viewDidLoad() {
    super.viewDidLoad()
    ntfObserver = NotificationCenter.default.addObserver(
          forName: .UIApplicationWillEnterForeground,
          object: nil, queue: nil) { (notification) in
        print("Application Will Enter Foreground")
    }
}
deinit {
    NotificationCenter.default.removeObserver(ntfObserver)
}

经过 Rx 来完成:

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.rx
        .notification(.UIApplicationWillEnterForeground)
        .subscribe(onNext: { (notification) in
            print("Application Will Enter Foreground")
        })
        .disposed(by: disposeBag)
}

你不需要去办理观察者的生命周期,这样你就有更多精力去重视事务逻辑。

多个使命之间有依靠关系

例如,先经过用户名暗码获得 Token 然后经过 Token 获得用户信息,

传统完成办法:

/// 用回调的办法封装接口
enum API {
    /// 经过用户名暗码获得一个 token
    static func token(username: String, password: String,
        success: (String) -> Void,
        failure: (Error) -> Void) { ... }
    /// 经过 token 获得用户信息
    static func userinfo(token: String,
        success: (UserInfo) -> Void,
        failure: (Error) -> Void) { ... }
}
/// 经过用户名和暗码获取用户信息
API.token(username: "beeth0ven", password: "987654321",
    success: { token in
        API.userInfo(token: token,
            success: { userInfo in
                print("获取用户信息成功: (userInfo)")
            },
            failure: { error in
                print("获取用户信息失利: (error)")
        })
    },
    failure: { error in
        print("获取用户信息失利: (error)")
})

经过 Rx 来完成:

/// 用 Rx 封装接口
enum API {
    /// 经过用户名暗码获得一个 token
    static func token(username: String, password: String) -> Observable<String> { ... }
    /// 经过 token 获得用户信息
    static func userInfo(token: String) -> Observable<UserInfo> { ... }
}
/// 经过用户名和暗码获取用户信息
API.token(username: "beeth0ven", password: "987654321")
    .flatMapLatest(API.userInfo)
    .subscribe(onNext: { userInfo in
        print("获取用户信息成功: (userInfo)")
    }, onError: { error in
        print("获取用户信息失利: (error)")
    })
    .disposed(by: disposeBag)

这样你能够防止回调阴间,然后使得代码易读,易维护。

KVO

传统完成办法:

func kvoTest() {
    self.person.addObserver(self, forKeyPath: "name", options: .new, context: nil)
}
override func observeValue(forKeyPath keyPath: String?,
               of object: Any?,
               change: [NSKeyValueChangeKey : Any]?,
               context: UnsafeMutableRawPointer?) {
    print(change as Any)
}
deinit {
    self.removeObserver(self.person, forKeyPath: "name", context: nil)
}

经过 Rx 来完成:

self.person.rx.observeWeakly(String.self, "name")
    .subscribe { value in
        print(value as Any)
    }
    .disposed(by: disposeBag)

RxSwift 的优势

  • 复合 – Rx 就是复合的代名词
  • 复用 – 由于它易复合
  • 清晰 – 由于声明都是不行变更的
  • 易用 – 由于它笼统了异步编程,使咱们一致了代码风格
  • 稳定 – 由于 Rx 是彻底经过单元测试的

关于开发的优缺点

优点

  • 代码简洁明了,可读性提高;
  • 有效完成数据与事务别离,便利进行单元测试;
  • 不必担心资源办理,它已经帮咱们做好了办理;
  • 由于它笼统的了异步编程,一致了代码风格。

缺点

  • 它是一整套结构,关于项目侵入性高;
  • 有一定的学习门槛,关于不熟悉原理的新手开发起来有难度。