UI layer tips
There are certain things that your Observable
s need to satisfy in the UI layer when binding to UIKit controls.
Threading
Observable
s need to send values on MainScheduler
(UIThread). That's just a normal UIKit/Cocoa requirement.
It is usually a good idea for you APIs to return results on MainScheduler
. In case you try to bind something to UI from background thread, in Debug build RxCocoa will usually throw an exception to inform you of that.
To fix this you need to add observeOn(MainScheduler.instance)
.
NSURLSession extensions don't return result on MainScheduler
by default.
Errors
You can't bind failure to UIKit controls because that is undefined behavior.
If you don't know if Observable
can fail, you can ensure it can't fail using catchErrorJustReturn(valueThatIsReturnedWhenErrorHappens)
, but after an error happens the underlying sequence will still complete.
If the wanted behavior is for underlying sequence to continue producing elements, some version of retry
operator is needed.
Sharing subscription
You usually want to share subscription in the UI layer. You don't want to make separate HTTP calls to bind the same data to multiple UI elements.
Let's say you have something like this:
let searchResults = searchText
.throttle(0.3, $.mainScheduler)
.distinctUntilChanged
.flatMapLatest { query in
API.getSearchResults(query)
.retry(3)
.startWith([]) // clears results on new search term
.catchErrorJustReturn([])
}
.shareReplay(1) // <- notice the `shareReplay` operator
What you usually want is to share search results once calculated. That is what shareReplay
means.
It is usually a good rule of thumb in the UI layer to add shareReplay
at the end of transformation chain because you really want to share calculated results. You don't want to fire separate HTTP connections when binding searchResults
to multiple UI elements.
Also take a look at Driver
unit. It is designed to transparently wrap those shareReply
calls, make sure elements are observed on main UI thread and that no error can be bound to UI.