Endless realm.write loop in session.addProgressNotification


#1

I recently hooked my iOS app (Swift) up to Realm Cloud and am pleased with the overall speed. I am creating a basic CRUD app and want to write to the user’s database whenever a database change is detected. According to the Realm Docs, the session.addProgressNotification(for: .download, mode: .reportIndefinitely)… seems perfect for that. However, when I create a write transaction in the progress.isTransferComplete, a new sync time is written to the realm database every second, like an endless loop. If I remove the write transaction and place a print statement in its place, the print statement is only executed when a change is detected. Why the difference in behavior?

//placed in viewWillAppear
indefCloudToken = session.addProgressNotification(for: .download,
                                                          mode: .reportIndefinitely) { progress in
                                                            
                                                            //https://docs.realm.io/sync/using-synced-realms/syncing-data#progress-notifications
                                                            if progress.isTransferComplete {
                                                                DispatchQueue.main.async {
                                                                    self.networkIndicatorBtnImg.setBackgroundImage(UIImage(named: "googleCheck"), for: .normal, barMetrics: .default)
                                                                    print("indefCloud being called")
                                                                    //
                                                                    guard let realm = self.realm else { return }
                                                                    let registeredUser = realm.objects(User.self)
                                                                    
                                                                    if registeredUser.first == nil {
                                                                        do {
                                                                            try realm.write {
                                                                                let user = User()
                                                                                user.lastSync = Date()
                                                                                
                                                                                realm.add(user)
                                                                            }
                                                                        } catch {
                                                                            fatalError()
                                                                        }
                                                                    } else {
                                                                        do {
                                                                            try realm.write {
                                                                                guard let registeredUser = registeredUser.first else { return }
                                                                                registeredUser.lastSync = Date()
                                                                                print("Sync time written to realm")
                                                                            }
                                                                        } catch {
                                                                            fatalError()
                                                                        }
                                                                    }
                                                                    
                                                                }
                                                                
                                                                
                                                            } else {
                                                                self.networkIndicatorBtnImg.setBackgroundImage(UIImage(named: "baseline-clear-24px"), for: .normal, barMetrics: .default)
                                                            }
                                                            
                                                            
        }

**sorry for the pyramid. I would typically break the functionality out into a type method but they wouldn’t help illustrate my point here.


#2

@joshRond The progress notification API is designed to, well, show the progress of sync - typically, for a bar that would show the percentage download completed. For instance, 10MB/100MB completed. If you then make a new write to that realm you have just increased the delta that needs to be synced - for instance, 10/102 - and on and on.

I would probably recommend you use a regular notificationToken for the use case you described.