Search code examples
iosswiftrealmgrand-central-dispatchbackground-process

DispatchGroup and Realm


My application uses Swift 3.1, Realm 2.7.0 as database and has a background service that uses the DispatchGroup to control my flow of a determined process.

First things first, in my ViewController I did an implementation of the Realm's notification system, knows as NotificationToken, that uses the method addNotificationBlock to detect any change of data in a determined object.

Until then, everything is ok. This block is invoked on all changes.

I have implemented a new process that uses a bunch of DispatchQueue and DispatchGroup, here is an example:

This code is just a sample! Don't do this!

DispatchQueue.global(qos: .background).async {

  autoreleasepool {

    //Other stuff...

    let id = 1337
    let dispatchGroup = DispatchGroup()

    dispatchGroup.enter()
    DispatchQueue(label: "Process").sync {

      let foo = Bar()

      foo.progress = { newValueInt in
        let realm = try! Realm()
        try! realm.write {
          realm
            .object(ofType: Some.self, forPrimaryKey: id)
            .someValue = newValueInt
        }
      }

      foo.completed = {
        dispatchGroup.leave()
      }

      foo.doSomethingAsync()

    }

    dispatchGroup.notify(queue: DispatchQueue.global(qos: .background)) {
      //Process completed.
    }

  }

}

The problem is: The addNotificationBlock is not invoked and the Object added on its notification block doesn't update when the method Bar.progress runs.

Thank you!


Solution

  • The solution is very simple, you just need to run the update on the main thread.

    foo.progress = { newValueInt in
        DispatchQueue.main.sync {
          let realm = try! Realm()
          try! realm.write {
            realm
              .object(ofType: Some.self, forPrimaryKey: id)
              .someValue = newValueInt
          }
        }
      }