RxSwift


ReactiveX(簡寫: Rx) 是一個可以幫助我們簡化異步編程的框架。

RxSwift 是 Rx 的 Swift 版本。

將KVO,異步操作 和 流 全部被統一成抽象序列

什么要使用 RxSwift ?

  • 復合 - Rx 就是復合的代名詞
  • 復用 - 因為它易復合
  • 清晰 - 因為聲明都是不可變更的
  • 易用 - 因為它抽象了異步編程,使我們統一了代碼風格
  • 穩定 - 因為 Rx 是完全通過單元測試的

RxSwift 能夠幫助我們做些什么:

Target Action

傳統實現方法:

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) 

這樣可以避免回調地獄,從而使得代碼易讀,易維護。

等待多個並發任務完成后處理結果

例如,需要將兩個網絡請求合並成一個,

通過 Rx 來實現:

/// 用 Rx 封裝接口 enum API {   /// 取得老師的詳細信息  static func teacher(teacherId: Int) -> Observable<Teacher> { ... }   /// 取得老師的評論  static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... } } /// 同時取得老師信息和老師評論 Observable.zip(  API.teacher(teacherId: teacherId),  API.teacherComments(teacherId: teacherId)  ).subscribe(onNext: { (teacher, comments) in  print("獲取老師信息成功: \(teacher)")  print("獲取老師評論成功: \(comments.count) 條")  }, onError: { error in  print("獲取老師信息或評論失敗: \(error)")  })  .disposed(by: disposeBag)

這樣幾行代碼來完成相當復雜的異步操作。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM