领域更新数据 + DispatchQueue [英] realm updating data + DispatchQueue

查看:62
本文介绍了领域更新数据 + DispatchQueue的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在后台更新了数据库.我的数据可以包含约 2000 项,更新需要时间.

I have update DataBase in background. My data can contain ~2000 items and it take time to update.

func updateData(items: [JSON], _ complete:@escaping() -> Void) {
    DispatchQueue.global(qos: .userInitiated).async {

       let currentModels = EgrnModel.getAllModels()
       var newModels: [EgrnModel] = []
       var toDelete: [EgrnModel] = []

       for model in currentModels {
           let contain = items.contains(where: {$0["id"].intValue == model.id})
           if !contain {
               toDelete.append(model)
           }
       }


       let realm = try! Realm()
       try! realm.write {
           for item in items {
               if let model = currentModels.first(where: {$0.id == item["id"].intValue}) {
                   model.update(item)
               }
               else {
                   newModels.append(EgrnModel(item))
               }
           }
           realm.delete(toDelete)
           realm.add(newModels)
       }

       DispatchQueue.main.async {
           complete()
       }
    }
}

而且我有一个功能,我需要立即更新数据.当我点击复选标记时,我冻结了.(我认为是因为此时其他数据正在后台更新)

and I have a function in which I need update data momentarily. When I tap checkmark I have a freeze. (I think it because at this time other data is updating in background)

func checkMark(index: Int) {

    let model = models[index]
    let realm = try! Realm()

    try! realm.write {
        model.needToUpdateOnServer = true
        model.lastEditUpdate = Date()
        model.read = true
    }
}

我尝试下一个代码来修复冻结.但是在这段代码中,我有一个崩溃 Terifying app 由于未捕获的异常 'RLMException',原因:'从错误的线程访问的领域.

I try next code to fix a freeze. But in this code I have a crash Terminating app due to uncaught exception 'RLMException', reason: 'Realm accessed from incorrect thread.

func checkMark(index: Int) {

    let model = models[index]

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

        let realm = try! Realm()

        try! realm.write {
            model.needToUpdateOnServer = true
            model.lastEditUpdate = Date()
            model.read = true
        }
    }
}

推荐答案

您需要将领域对象从一个线程移动"到另一个线程,因为领域对象不是线程安全的,而是线程受限的.为此,您必须使用 ThreadSafeReference API.

What you need to is "move" realm objects from one thread to another because realm objects are not thread-safe but Thread Confined. To achieve this you have to use ThreadSafeReference API.

要解决此问题,请执行以下操作:

To solve this problem do the following:

  1. 在领域类上创建扩展

extension Realm {
    func writeAsync<T : ThreadConfined>(obj: T, errorHandler: @escaping ((_ error : Swift.Error) -> Void) = { _ in return }, block: @escaping ((Realm, T?) -> Void)) {
        let wrappedObj = ThreadSafeReference(to: obj)
        let config = self.configuration
        DispatchQueue(label: "background").async {
            autoreleasepool {
                do {
                    let realm = try Realm(configuration: config)
                    let obj = realm.resolve(wrappedObj)

                    try realm.write {
                        block(realm, obj)
                    }
                }
                catch {
                    errorHandler(error)
                }
            }
        }
    }
}

  1. 以这种方式在您的代码中使用它

func checkMark(index: Int) {

    let model = models[index]
    let realm = try! Realm()

    realm.asyncWrite(model) { realm, model in
        model.needToUpdateOnServer = true
        model.lastEditUpdate = Date()
        model.read = true
    }
}

这篇关于领域更新数据 + DispatchQueue的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆