我们可以在后台队列中生成Realm结果并在主线程上使用它吗

Win*_*ero 6 realm ios swift

我最近开始使用Realm,不确定我的用例是否有效:

通常,当从数据库读取大量数据时,我想将其放在后台队列中,以便它将异步获取数据,然后在主线程上使用它。

例如,我想获取一些基于城市的结果:

    private var results: [Results<SomeObject>?] = []
    autoreleasepool {
        DispatchQueue(label: "background").async {
            [unowned self] in
            do
            {
                let realm = try Realm()
                for i in 1...City.count
                {
                    self.results.append(realm.objects(SomeObject.self).filter("city=\(i)"))
                }
            }
            catch
            {
                NSLog("Failed to open Realm instance on background qeueue")
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

稍后用于results更新我的图表:

cell.setChartData(ChartDataFactory.createCombinedData(from: results[0]))

但是,如果我将此模型应用于Realm,则会收到类似

由于未捕获的异常“ RLMException”而终止应用程序,原因:“从错误的线程访问了领域。

我知道我必须为每个线程使用领域,并且可以通过在主线程上读取领域来做到这一点,但是我不希望领域查询阻塞我的主线程。

有什么办法可以实现我的目标?例如,在后台队列中读取领域并从另一个线程访问结果,同时保留自动刷新功能。

谢谢。

Tho*_*yne 6

Realm 具有在后台线程上运行查询并使用Results.observe()将结果传送到主线程的内置功能。

如果您特别需要执行无法表示为 Realm 查询的昂贵过滤逻辑,您可以使用ThreadSafeReference在线程之间手动传递对象数组。

从 5.0 开始,您现在可以在后台线程上构造查询并使用以下on:参数在主线程上接收通知observe()

DispatchQueue.global().async {
    let realm = try! Realm()
    let results = realm.objects(ObjectType.self).filter("property in %@", expensiveFunction(realm))
    self.token = results.observe(on: .main) { change in
        // do stuff with the results on the main thread
    }
}
Run Code Online (Sandbox Code Playgroud)