RxRealm (RealmSwift Part 7)

https://realm.io/docs/swift/latest/

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 Observables from objects of type Results, List, LinkingObjects or AnyRealmCollection. 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

Reading and writing can happen in different spots in the project, on different threads, from different processes, or, when using the Realm Platform, from anywhere in the world. Each class in the app can focus on the business logic and forget about the notion of outdated or cached data, since Realm objects are always up to date.

Figure 1

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.

  1. Fetch all users from realm database in users variable. Since there is no User object users initial count = 0 . users variable is Results<User> Realm data type
  2. Observable.collection returns an `Observable<E>`in our case Observable<Results<User>> that emits each time the collection data changes.The observable emits an initial value upon subscription. You won’t notify until you subscribe the observable using .subscribe method
  3. onNext method will call every time you add,update or remove user object in the database
  4. 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 process onNext still will call
  5. Observable.collection under the hood use Realm Collection notification mechanism
Figure 2

Delete the application and run the code shown in Figure 3 there is one point to note

  1. Observable.array works same as Observable.collection but it will return Swift Observable<Array<User>> instead of Realm Observable<Results<User>>. This is helpful when your business logic depends on Swift array instead of Realm Results
Figure 3

Delete the application and run the following code to save objects into the database as shown in Figure 4

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

Figure 5

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

  1. First thing to understand is that changeset notification will fire when write transaction is completed
  2. Second thing is that changeset notification will help to update UITableView smartly, so the information is giving to help UITableView
  3. Let’s say you have a UITableView populate with user1,user2 and user3 in the order respectively
  4. Now when you delete user1 which is at index 0 it deleted it and user3 which is last index move to index 0
  5. After that we update user object at index 0 at that time user3 firstName will update
  6. Write transaction now end , Notification will fire with these information as shown in Figure
  7. Now UItableview delete row at index 0 and 3 (user 1 and user 3 rows are deleted)
  8. After that it insert row at 0 in this case user3 will move to index 0 in UITableView
Figure 6

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 falseas shown in Figure 7.1

Figure 7
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

  1. This API uses the Realm object notifications under the hood to listen for changes which I already cover in this part
  2. As shown in Figure 8.1 we update property since it is in the observing list you get the change
Figure 8
Figure 8.1

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

Figure 9

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

Useful Links

https://github.com/RxSwiftCommunity/RxRealm

Senior iOS Engineer | HungerStation | Delivery Hero