领域从错误的线程访问 - 再次 [英] Realm accessed from incorrect thread - again

查看:138
本文介绍了领域从错误的线程访问 - 再次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到访问realm对象有很多问题,我认为我的解决方案就是解决这个问题。

I noticed many problems with accessing realm object, and I thought that my solution would be solving that.

所以我写了这样简单的帮助方法:

So I have written simple helping method like this:

public func write(completion: @escaping (Realm) -> ()) {
    DispatchQueue(label: "realm").async {
        if let realm = try? Realm() {
            try? realm.write {
                completion(realm)
            }
        }
    }
}

我认为完成块会很好,因为每次我写对象或更新它时,我都会使用上面的方法。

I thought that completion block will be fine, because everytime I write object or update it, I use this method above.

不幸的是我收到错误:

libc++abi.dylib: terminating with uncaught exception of type realm::IncorrectThreadException: Realm accessed from incorrect thread.


推荐答案

Realm的实例 Object 是包含线程的。它们不能在线程之间传递或者会发生异常。

Instances of Realm and Object are thread-contained. They cannot be passed between threads or that exception will occur.

因为你传递了完成块本身在创建队列的同时进行后台队列(正如Dave Weston所说),该块内的任何Realm对象肯定不会在同一个线程上创建,这可以解释这个错误。

Since you're passing the completion block itself to the background queue at the same time the queue is being created (As Dave Weston said), any Realm objects inside that block will most certainly not have been created on the same thread, which would explain this error.

像Dave说的那样,每次调用该方法时都会创建一个新的调度队列。但是为了扩展这一点,iOS也无法保证在同一个线程上一致地调用单个队列。

Like Dave said, you're creating a new dispatch queue every time you call that method. But to expand upon that, there's also no guarantee by iOS that a single queue will be consistently called on the same thread.

因此,Realm的最佳实践是重新创建每次要在该线程上执行新操作时,您的Realm对象都在同一个线程上。 Realm在每个线程的基础上在内部缓存 Realm 的实例,因此调用 Realm()所涉及的开销很小多次。

As such, best practice with Realm is to recreate your Realm objects on the same thread each time you want to perform a new operation on that thread. Realm internally caches instances of Realm on a per-thread basis, so there's very little overhead involved with calling Realm() multiple times.

要更新特定对象,您可以使用新的 ThreadSafeReference 功能重新访问同一个对象后台线程。

To update a specific object, you can use the new ThreadSafeReference feature to re-access the same object on a background thread.

let realm = try! Realm()
let person = Person(name: "Jane") // no primary key required
try! realm.write {
  realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "com.example.myApp.bg").async {
  let realm = try! Realm()
  guard let person = realm.resolve(personRef) else {
    return // person was deleted
  }
  try! realm.write {
    person.name = "Jane Doe"
  }
}

这篇关于领域从错误的线程访问 - 再次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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