Observe JSON response if changed from already saved in Database(Realm)


(Ahsan) #1

Building an App which is using Alamofire and Realm for Network call and data storage respectively with help of RxSwift. Every thing is working fine but the need of the day is to prevent always refresh views on network call. For now app’s behaviour is like I replicate JSON response to DB and then update views from DB. But to always get latest response app needs to call Network API on every viewWillAppear. But I don’t want to get all DB data and search if there is something changed from new response and then display it. So is there any thing in Swift or Alamofire or Realm that I can observe on if the data is different from previously loaded in database and then only app will update its view.

self?.notificationToken = Database.singleton.fetchStudentsForAttendence(byCLassId: classId).observe { [weak self] change in
                switch change {
                case .initial(let initial):
                    TestDebug.debugInfo(fileName: "", message: "INIT: \(initial)")
                    self!.viewModel.getStudentsData(id: classId)
                case .update(_, let deletions, let insertions, let modifications):
                    print(modifications)
                    TestDebug.debugInfo(fileName: "", message: "MODIFY: \(modifications)")
                    TestDebug.debugInfo(fileName: "", message: "MODIFY: \(insertions)")
                case .error(let error):
                    TestDebug.debugInfo(fileName: "", message: "ERROR:\(error)")
                }
            }

this is how I am observing data now, but As I every time save response into database when I call the API, and I am using case .initial to monitor that and as database always have been refreshed and this block calls every time. I need something that monitors that data value changed in DB. Is there something in Realm for that ?


(jay) #2

The question is a bit unclear so this may be totally off base. Let me add a couple of pieces of info.

Realm results objects are live updating objects. If, for example, you load in some Dog Objects

var dogResults: Results<DogClass>? = nil //define a class var

self.dogResults = realm.objects(Dog.self) //populate the class var

and then if you change a dog name somewhere else in your code, the dogResults class var will contain the updated name of that dog.

So, you don’t need to continually refresh that results object as it’s done automatically.

If you want to be notified of those changes, you add an observer to the dogResults class var.

self.notificationToken = self.dogResults!.observe { (changes: RealmCollectionChange) in

When you first add an observer, the .initial block is called once and only once. It is not called any time after that. That’s where you would say, refresh your tableView to present the initial data.

When data changes, the .update block is called. You can choose to just reload the tableView again or can make fine-grained changes to your tableView based on the changed data.

Your question states

But to always get latest response app needs to call Network API on every viewWillAppear.

which isn’t necessary as the class var dogResults always contains updated info.

and along those same lines

every time save response into database when I call the API

isn’t necessary as the only time you will need to update the UI is from within the .update block.

Lastly, this piece of code seems to be out of place

self!.viewModel.getStudentsData(id: classId)

however, there’s not enough code in the question to understand why that’s being called in .initial - you may want to consider using the approach presented above instead of polling for updates.


(Ahsan) #3

Okay but one thing I didn’t get from your wonderful answer is that if I have a table view and it has data in it, and i have different cell types for them and, after the api call they all get updated with new data as realm is live. but my view are not shifting as if the data is updated. even after switching tabs and i can see that data is being updated. but i can I notify my views that without reloading them even if I come back from other view controller they did not get changed. how can I deal with that ?


(jay) #4

Cross post to StackOverflow question

Observe JSON response if changed from already saved in Database(Realm)