0

RxSwift những khái niệm cơ bản P.3

Chào các bạn, hôm nay tôi tiếp tục nói về những khái niệm cơ bản của thư viện RxSwift bao gồm :

  • KVO
  • UI layer tips
  • Making HTTP requests

KVO

Có 2 cách để sử dụng KVO.

// KVO
extension Reactive where Base: NSObject {
    public func observe<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions, retainSelf: Bool = true) -> Observable<E?> {}
}
#if !DISABLE_SWIZZLING
// KVO
extension Reactive where Base: NSObject {
    public func observeWeakly<E>(type: E.Type, _ keyPath: String, options: NSKeyValueObservingOptions) -> Observable<E?> {}
}
#endif

Ví dụ cách quan sát frame của UIView. Chú ý : UIKit không hỗ trợ KVO.

view
  .rx.observe(CGRect.self, "frame")
  .subscribe(onNext: { frame in
    ...
  })

hoặc

view
  .rx.observeWeakly(CGRect.self, "frame")
  .subscribe(onNext: { frame in
    ...
  })

UI layer tips

Observables cần tuân theo UI layer khi làm việc với UIKit controls.

Threading

Observables cần gửi giá trị trên MainScheduler(UIThread). Trường hợp bạn muốn gửi gì đó lên UI trong background thread, RxCocoa sẽ gửi exception. Để giải quyết vấn đề này bạn cần thêm observeOn(MainScheduler.instance). NSURLSession extensions mặc định sẽ không trả kết quả trên MainScheduler.

Errors

Nếu không biết Observable có thể lỗi hay không, bạn có thể sử dụng catchErrorJustReturn(valueThatIsReturnedWhenErrorHappens), để đảm bảo nó không bị lỗi. Nếu muốn sequence tiếp tục sinh ra element có thể sử dụng retry operator.

Dùng chung subscription

Bạn thường muốn sử dụng chung subscription trong UI layer vì không cần thiết phải gọi nhiều HTTP request khác nhau để đưa cùng một dữ liệu lên nhiều UI element. Ví dụ:

let searchResults = searchText
    .throttle(0.3, $.mainScheduler)
    .distinctUntilChanged
    .flatMapLatest { query in
        API.getSearchResults(query)
            .retry(3)
            .startWith([]) //
            .catchErrorJustReturn([])
    }
    .shareReplay(1)

Sử dụng shareReplay để chia sẻ kết quả tìm kiếm mỗi lần tính toán như vậy sẽ không cần thiết phải sử dụng nhiều kết nối HTTP để đưa kết quả searchResults lên nhiều UI elements.

Thực hiện HTTP requests

Đầu tiên, ta sẽ tạo NSURLRequest object tương ứng với công việc cần thực hiện. Request được xác đinh là GET hay POST, phần body, các query parameters . Cách tạo GET request

let request = NSURLRequest(URL: NSURL(string: "http://en.wikipedia.org/w/api.php?action=parse&page=Pizza&format=json")!)
Nếu muốn thực hiện request với các observable khác:
let responseJSON = NSURLSession.sharedSession().rx.JSON(request)

// ở đây sẽ request sẽ không được thực hiện
// `responseJSON`  mô tả cách fetch dữ liệu trả về
let cancelRequest = responseJSON
    // request được thực hiện
    .subscribe(onNext: { json in
        print(json)
    })

NSThread.sleep(forTimeInterval: 3.0)

// Nếu muốn hủy request sau 3s
cancelRequest.dispose()

NSURLSession extensions mặc định sẽ không trả về kết quả trên MainScheduler.

Bạn cũng có thể sử dụng :

NSURLSession.shared.rx.response(myNSURLRequest)
    .debug("my request")
    .flatMap { (data: NSData!, response: NSURLResponse!) -> Observable<String> in
        if let response = response as? NSHTTPURLResponse {
            if 200 ..< 300 ~= response.statusCode {
                return just(transform(data))
            }
            else {
                return Observable.error(yourNSError)
            }
        }
        else {
            rxFatalError("response = nil")
            return Observable.error(yourNSError)
        }
    }
    .subscribe { event in
        print(event)
    }

trong lần sau tôi sẽ nói về ứng dụng của rxswift trong giải quyết một số bài toán trong lập trình iOS, hẹn gặp lại các bạn.

RxSwift các khái niệm cơ bản P.1

RxSwift các khái niệm cơ bản P.2


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.