12/08/2018, 16:19

Action trong Rxswift

Creating an Action Action là một class chung chung được định nghĩa là class Action<Input, Element>. Input là loại dữ liệu đầu vào được cung cấp cho chức năng. Element là loại phần tử được phát ra bởi các hàm trả về. Ví dụ đơn giản nhất của một Action không có input, thực hiện một số công ...

Creating an Action

Action là một class chung chung được định nghĩa là class Action<Input, Element>. Input là loại dữ liệu đầu vào được cung cấp cho chức năng. Element là loại phần tử được phát ra bởi các hàm trả về. Ví dụ đơn giản nhất của một Action không có input, thực hiện một số công việc và hoàn thành mà không sản xuất ra dữ liệu:

let buttonAction: Action<Void, Void> = Action {
  print("Doing some work")
  return Observable.empty()
}

Điều này đơn giản là chết. Còn bây giờ là hành động lấy chứng chỉ, thực hiện request network và trả về trạng thái đã login chưa?

let loginAction: Action<(String, String), Bool> = Action { credentials in
  let (login, password) = credentials
  // loginRequest returns an Observable<Bool>
  return networkLayer.loginRequest(login, password)
}

Lưu ý: Mỗi action thực hiện được xem là hoàn chỉnh khi có thể quan sát và trả về bởi closure complete hoặc error. Điều này ngăn việc bắt đầu nhiều hành động dài. Hành vi này tiện dụng với các yêu cầu mạng bạn sẽ thấy bên dưới.

Action trông có vẻ hữu ích ngay từ cái nhìn đầu tiên nhưng có thể không rõ ràng ngay cách sử dụng của nó, vì vậy chúng ta hãy cùng xem xét vài ví dụ thực tiễn.

Connecting buttons

Action đi kèm với phần mở rộng phản ứng cho UIButton và một số thành phần UIKit khác. Nó cũng định nghĩa CocoaAction, một typealias cho Action<Void, Void> - hoàn hảo cho các Button mà không cần mong đợi một đầu ra Để kết nối button, chỉ cần làm như sau:

  button.rx.action = buttonAction

Mỗi khi người dùng nhấn nút, hành động sẽ được thực thi, Nếu hành động từ lần nhấn trước đó không hoàn chỉnh, tap đó sẽ bị loại. Loại bỏ hành động từ button bằng cách thiết lập nó nil:

  button.rx.action = nil

Composing behavior

Hãy xem xét loginAction một lần nữa từ ví dụ Tạo một Action. Kết nối nó với giao diện người dùng của bạn như sau:

let loginPasswordObservable =
Observable.combineLatest(loginField.rx.text, passwordField.rx.text) {
($0, $1) }
loginButton
  .withLatestFrom(loginPasswordObservable)
  .bindTo(loginAction.inputs)
  .addDisposableTo(disposeBag)

Mỗi lần người dùng nhấn vào nút Đăng nhập, giá trị mới nhất của trường đăng nhập và mật khẩu được phát ra cho đầu vào của observer của loginAction. Nếu hành động chua được thực hiện (chẳng hạn như nếu lần đăng nhập trước đó không diễn ra), closure được thực hiện, yêu cầu đăng nhập mới được bắt đầu và kết quả có thể quan sát được trả về giá trị true hoặc false, hoặc nó sẽ báo lỗi ngoài.

Bây giờ bạn có thể subscribe vào các yếu tố của action, có thể quan sát và được thông báo khi đăng nhập thành công:

loginAction.elements
  .filter { $0 }        // only keep "true" values
  .take(1)
  .subscribe(onNext: {
    // login complete, push the next view controller
  })
  .addDisposableTo(disposeBag)

Có hai loại lỗi:

  • notEnabled - hành động đã được thực hiện hoặc bị vô hiệu hoá.
  • underlyingError(error) - lỗi phát sinh bởi trình tự cơ bản. Xử lý chúng théo cách này:
loginAction
  .errors
  .subscribe(onError: { error in
    if case .underlyingError(let err) = error {
      // update the UI to warn about the error
} })
  .addDisposableTo(disposeBag)

Passing work items to cells

Action giúp giải quyết một vấn đề phổ biến: Cách kết nối các button trong table view cells. Khi cấu hình một cell, bạn chỉ định một hành động cho một nút. Bằng cách nàym bạn không cần đặt công việc thực thế bên trong cách subclass cell của bạn, giúp thực hiện các công việc tách biệt và sạch sẽ - thậm chí còn quan trọng hơn nếu bạn đang sử dụng kiến trúc MVVM. Sử dụng lại một ví dụ từ một chương sách nấu ăn, đây là cách đơn giản để bind một button:

observable.bindTo(tableView.rx.items) {
  (tableView: UITableView, index: Int, element: MyModel) in
  let cell = tableView.dequeueReusableCell(withIdentifier: "buttonCell",
for: indexPath)
  cell.button.rx.action = CocoaAction { [weak self] in
    // do something specific to this cell here
    return .empty()
  }
return cell }
.addDisposableTo(disposeBag)

Tất nhiên bạn có thể thiết lập một action đã có thay vì tạo mới. Khả năng là vô tận !!

Manual execution

Để thực hiện một hành động thủ công, hãy gọi hàm execute(            </div>
            
            <div class=

0