RxSwift Part 5 (RxCocoa)
This is the continuation of previous part 4. In this part we will cover RxCocoa
UITextField
in Rx way- Use case of
throttle
operator - Why RxCocoa
- UIButton in Rx way
- Use Case of
combineLatest
operator - Use Case of
share(replay:)
operator UITableView
in Rx way- API Request in Rx way
RxSwift → is a framework for interacting with the Swift programming language, in a reactive manner
RxCocoa → is a framework that makes Cocoa APIs used in iOS and OS X easier to use with reactive techniques
OR
RxCocoa provide wrapper to Cocoa API’s to adopt reactive environment
UITextField
As shown in Figure 1 we subscribed to UITextField using RxCocoa
Few things to note
- By calling rx, you access the RxCocoa extensions for the relevant class. In this case, it’s a UITextField. (UITextField+Rx.swift)
.text
return the the contents of the text field as an Observable value. text is another RxCocoa extension, This is the same property UITextField already has but in this extension you can subscribe to it. So when User enter any text in the UITextField it update text property and you will get the value inn subscription blockobserveOn
→ It allows you to change the scheduler on which the observer code will be executed. We will discuss this in detail laterthrottle
since user can typing so fast and passing to subscriber for every key press could be computationally expensive and lead to a lagging UI. In part3 We discussed throttle and debounce in detailnotNilValue
operator we created in part3. This will filter nil and unwrap the optional value . There is a same operator in RxSwift extension called unwrap
As shown in Figure 2 we are validating password field and returning whether user enter password according to the rules defined.
You can add many operators in between to obtain what you want as I added filter operator to notified my subscriber when user pass our rules. We can chain functions, meaning that each function takes the result of the previous function but it should return Observable sequence that can be observe
Why RxCocoa
So, the question is What is the need of UITextField reactive things if they have a textChange
delegate method that also is reactive and the answer is
- There are some different ways to pass information from one object to another in iOS reactively (Notification, pass in closure, delegate, KVO, & target/action,) each of these different systems may be simple by itself but most of the complexity in the logic of an iOS app is in having to convert from one of these systems to another. RxSwift/RxCocoa replaces virtually all of these systems with one which is in a Rx way.
- To compatible with RxSwift stuff and to easily work with Rxswift Observable things. Like UITextField return Observable same like RxSwift so that you can use RxSwift operators and whole it’s API
- To used all of your RxSwift skills in Cocoa API’s as well
UIButton
Few things to note
- By calling rx, you access the RxCocoa extensions for the relevant class. In this case, it’s a UIButton. (UIButton+Rx)
.tap
Reactive wrapper for `TouchUpInside` control event. It return the Observable sequence where you can apply Rx operators tools according to your case. This is one of the reason we have RxCocoa.bind
subscribes an element handler to an observable sequence that is return after filtered from throttle operator
What If we want when if userName is not empty and password field is valid than change login Button color as shown in Figure 5
As shown in Figure 4 we did this. There . are few things to be note
- Clear debugging information for new developer , Let’s say new developer want to understand all the login button logic he only need to see this method and it works. In imperative programming he need to search all its usage in the controller
validUserName
observer will first get the unwrap text fromUITextField
for every 0.5 sec and check if its valid and there is a change in the validation output then it send to all subscriber and same for. validPasswordName
- Loginbutton combining both
userName
andpassword
textField latest value and associates color logic on this. part3 We discussedcombineLatest
in detail
As shown in Figure 6 everythingValid observable created twice. Remember in part 3 we said create method gets executed as many times as we subscribe. In this case . we are binding twice which is same as subscription. One button for color logic and second for button interaction state. So how we solve it
As shown in figure 7 wee used share(replay:1)
which create a single observable that is share between all subscription . In part 3 we discussed this operator in detail
Same for validUserName
observable . First time it create when we called validUserName.subscribe
and second time when Observable.combineLatest(validUserName, validPasswordName)
is called. The solution is same as above
Add share(replay:1)
to validPasswordName
and validUserName
will solve this
UITableView
There are few things to be noted
- As discussed in part 1 we need dispose subscription to avoid memory leak using DisposeBag. DisposeBag is a bag (or collection) of disposables. when you subscribe to any observables you add disposables to this bag Because of adding the Disposable into the DisposeBag it means the DisposeBag have a strong reference to Disposable, since the bag is the controller property and when the view controller is deallocated, its variables (including the bag) are deallocated. When the disposeBag is deallocated, its deinit function calls dispose on all of the disposables it contains
users
variable containsBehaviorRelay
observable sequence. BehaviorRelay we disccussed detail in part 2. “ABehaviorRelay
wraps a Behavior Subject.What makes it different from Behavior Subject is that it never terminated means you can’t call completed,error or dispose method on observable subject and you can ask it for its current value without subscribing to receive updates which is very helpful”- We fetched all users from Github and store in users variable by using accept method in
BehaviorRelay
which will immediately emit data to all it’s subscriber - Called
bind(to:)
to associate theusers
observable with the code that executes each row in the table view. - By calling rx, you access the RxCocoa extensions for the relevant class. In this case, it’s a UITableView. (UITableView+Rx.swift)
- Pass in a block for each new item. This is the same as
cellForRow
method and added this subscription to the disposable bag - RxCocoa adds to UITableView called modelSelected(_:). This returns an Observable you can use to watch information about selected model objects. Reactive wrapper for
delegate
messagetableView:didSelectRowAtIndexPath
Our fetchdata
is not reactive let’s make it Reactive. Let’s discuss line by line
send
method returnObservable sequence<T>
whereT
should conformed toCodable
protocol. We used Single Observable sequence. A Single is a variation of Observable that, instead of emitting a series of elements, is always guaranteed to emit either a.success
or an.error.
as discussed in Part 2fetchData
first create urlRequest , then call api and andonSuccess
assign data to users observable