在后台线程中写入Realm后,主线程看不到更新的数据

苏文梁*_*苏文梁 10 multithreading realm ios swift

  1. 清除数据库.
  2. 进行API调用以获取新数据.
  3. 将从API检索的数据写入后台线程中的数据库中.
  4. 从主线程上的数据库中读取数据并呈现UI.

在步骤4中,数据应该是最新数据,但我们没有看到任何数据.

// remark: all main thread shared a realm object
DBManager.deleteAll()
// call api success, get newdata
DispatchQueue.global(qos: .background).async { 
    DBManager.initDBData(<newdata>)
    DispatchQueue.main.async {
        print("has data?????", DBManager.getBrands().count)
     }
 }

// when write
func write() {
    let realmBackgroud = try! Realm()
    try! realmBackgroud.write {}
 }
Run Code Online (Sandbox Code Playgroud)

bda*_*ash 11

具有runloops的线程上的Realm实例(例如主线程)由于通知被发布到其线程的runloop而更新到Realm文件中的最新数据版本.在后台线程上提交写入事务与另一个线程的runloop接收到该通知之间存在时间窗口,并且由于CFRunLoop处理其调度队列相对于其通知源的顺序,对于dispatch_async主队列来说并不罕见在提交通知之后立即执行写入事务之前执行.

有几种方法可以解决此问题:

  • 使用Realm的通知机制之一(例如集合通知)来响应您在后台线程上所做的更改,而不是显式使用dispatch_async.
  • Realm.refresh()无论线程是否有机会处理触发自动刷新的通知,都会在块的顶部显式调用您调度到主队列以使其自身达到最新版本.