swift 从不正确的线程访问领域-再次

mftmpeh8  于 12个月前  发布在  Swift
关注(0)|答案(5)|浏览(123)

我注意到访问领域对象的许多问题,我认为我的解决方案将解决这个问题。
所以我写了一个简单的帮助方法,像这样:

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

字符串
我认为完成块会很好,因为每次我写对象或更新它时,我都会使用上面的方法。
很不幸,我得到了错误:

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

n9vozmp4

n9vozmp41#

RealmObject的数组是线程包含的。它们不能在线程之间传递,否则会发生异常。
由于在创建队列的同时将completion块本身传递给后台队列(正如Dave韦斯顿所说),该块中的任何Realm对象肯定不会在同一线程上创建,这可以解释此错误。
就像Dave说的,每次调用该方法时都要创建一个新的调度队列。但要扩展到这一点,iOS也不能保证在同一线程上始终调用单个队列。
因此,Realm的最佳实践是每次要在同一线程上执行新操作时,都在该线程上重新创建Realm对象。Realm在每个线程的基础上内部缓存Realm的示例,因此多次调用Realm()所涉及的开销非常小。
要更新特定对象,可以使用the new ThreadSafeReference feature在后台线程上重新访问同一对象。

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"
  }
}

字符串

qlzsbp2j

qlzsbp2j2#

方法在每次调用时都会创建一个新的DispatchQueue
DispatchQueue(name:"")是一个初始化器,而不是一个查找。如果你想确保你总是在同一个队列上,你需要存储一个对那个队列的引用并分派到它。
您应该在设置Realm时创建队列,并将其存储为执行设置的类的属性。

cmssoen2

cmssoen23#

也许这对某人有帮助(因为我花了几个小时寻找解决方案)
在我的例子中,我在后台将JSONMap到模型(导入ObjectMapper_Realm)时发生了崩溃。同时,主线程上分配了一个realm示例。

px9o7tmv

px9o7tmv4#

通常情况下,当你在不同的线程中初始化它并试图从不同的线程访问或修改时,它会发生。只需放置一个调试器来查看初始化的线程并尝试使用相同的线程。

kjthegm6

kjthegm65#

在我使用Realm情况下,不要使用PMAC,只使用同步

相关问题