RxRealm (RealmSwift Part 7)
This is the continuation of the previous part . If you know the basics operation in Realm and you have read RxSwift blog then you can continue this part. I will not going to cover what is RxSwift , Observables and Observer since it was done in Rx part.
RxRealm
It’s a lightweight wrapper or extension above RxSwift that converts Realm dataTypes into RxObservables which you can observe and react when they change
RxRealm can be used to create
Observable
s from objects of typeResults
,List
,LinkingObjects
orAnyRealmCollection
. These types are typically used to load and observe object collections from the Realm Mobile Database.
Live results in Realm
Realm result sets always return the latest up-to-date data. Data in Results is never outdated. This means you never have to reload results from disk or somehow manually refresh in- memory data.
As shown in Figure 1 we got the new user and we didn’t fetch using realm.objects
method instead newly added object are presented on users variable . If you come from Core data background you need to again fetched object from the stack
Even if you always access the latest up-to-date data, you still need to know when that data changes so you can update your app’s UI accordingly. In short we don’t have any mechanisms to know that data has changed so that we can update our UI.
To solve this problem Realm has a notification mechanism that lets you notify about when your data changes, and more importantly, it gives you precise fine-grained information about what was changed. Realm notification was done in previous part
In this part we will solve this problem using RxRealm .
Getting Started
The code shown in Figure 2 performed number of tasks.
- Fetch all users from realm database in
users
variable. Since there is no User objectusers
initial count = 0 .users
variable is Results<User> Realm data type Observable.collection
returns an`Observable<E>`
in our caseObservable<Results<User>>
that emits each time the collection data changes.The observable emits aninitial value upon subscription.
You won’t notify until you subscribe the observable using .subscribe
methodonNext
method will call every time you add,update or remove user object in the database- As shown in Figure
onNext
is called when user1 and user2 is added to the database. Note: If we add user1 from different thread or even with different processonNext
still will call Observable.collection
under the hood use Realm Collection notification mechanism
Delete the application and run the code shown in Figure 3 there is one point to note
Observable.array
works same asObservable.collection
but it will return SwiftObservable<Array<User>>
instead of RealmObservable<Results<User>>.
This is helpful when your business logic depends on Swiftarray
instead of RealmResults
Delete the application and run the following code to save objects into the database as shown in Figure 4
Figure 5 used Observable.changeset
which emits every time the collection changes and provides the exact indexes that has been deleted, inserted or updated: and as shown since we update user at index 0 it printed 1 element is updated at index 0 and we take this information to update row at index 0 instead of reloading whole tableview if we are populating this in a UITableview
After you run the below code you will surprise by the changeset results 😕 You will definitely have a question why it is saying delete at index 0 and 2 and insert object at index 0 , but we only delete object at index 0 and then update object at index 0. So let’s break and understand things
- First thing to understand is that changeset notification will fire when write transaction is completed
- Second thing is that changeset notification will help to update UITableView smartly, so the information is giving to help UITableView
- Let’s say you have a UITableView populate with user1,user2 and user3 in the order respectively
- Now when you delete user1 which is at index 0 it deleted it and user3 which is last index move to index 0
- After that we update user object at index 0 at that time user3 firstName will update
- Write transaction now end , Notification will fire with these information as shown in Figure
- Now UItableview delete row at index 0 and 3 (user 1 and user 3 rows are deleted)
- After that it insert row at 0 in this case user3 will move to index 0 in UITableView
Observable.changeset
has array variant as well Observable.arrayWithChangeset(from:synchronousStart:)
Observing a single object
Delete the application and run the code snippet written in Figure 4 and then run again and as shown in Figure 7 it emits the object initial state as its first next
event after subbscription. You can disable this behavior by using the emitInitialValue
parameter and setting it to false
as shown in Figure 7.1
You can set changes to which properties constitute an object change you’d like to observe for: In our case we are observing passport property of User object and as shown in Figure 8 we updated user firstName and it didn’t trigger subscriber block.There are things to be aware of
- This API uses the Realm object notifications under the hood to listen for changes which I already cover in this part
- As shown in Figure 8.1 we update property since it is in the observing list you get the change
As shown in Figure 9 we used propertyChanges:
which provides information about which properties changed, along with the changed values, old and new.Note: Observer will automatically dispose when the object is deleted from realm
Since I am not a fan of RxCocoa I will not cover Automatically binding table and collection views. In my project I only use Rx where it is necessary like in one of my project we have a lots of polling of data and database object is changing very frequently on background I used Realm notification but we are using some kind of repository pattern and there is no realm object in business logic so I used Rx that acts as a wrapper between Realm notification and swift DTO’s which is driving the business logic so in future If there is a change in the database we don’t have to change the business logic
Next
In the next part I will use RxSwift only to make Realm datatypes Observables without using RxRealm