当前位置:  开发笔记 > IOS > 正文

领域从错误的线程访问 - 再次

如何解决《领域从错误的线程访问-再次》经验,为你挑选了2个好方法。

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

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

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.

TiM.. 24

实例RealmObject线程包含.它们不能在线程之间传递,否则将发生异常.

由于你在completion创建队列的同时将块本身传递给后台队列(如Dave Weston所说),该块内的任何Realm对象肯定不会在同一个线程上创建,这可以解释这个错误.

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

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

要更新特定对象,可以使用新ThreadSafeReference功能在后台线程上重新访问同一对象.

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


Dave Weston.. 7

DispatchQueue每次调用它时,您的方法都会创建一个新方法.

DispatchQueue(name:"")是初始化程序,而不是查找.如果要确保始终位于同一队列中,则需要存储对该队列的引用并将其分派给它.

您应该在设置Realm时创建队列,并将其存储为执行安装的类的属性.



1> TiM..:

实例RealmObject线程包含.它们不能在线程之间传递,否则将发生异常.

由于你在completion创建队列的同时将块本身传递给后台队列(如Dave Weston所说),该块内的任何Realm对象肯定不会在同一个线程上创建,这可以解释这个错误.

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

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

要更新特定对象,可以使用新ThreadSafeReference功能在后台线程上重新访问同一对象.

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



2> Dave Weston..:

DispatchQueue每次调用它时,您的方法都会创建一个新方法.

DispatchQueue(name:"")是初始化程序,而不是查找.如果要确保始终位于同一队列中,则需要存储对该队列的引用并将其分派给它.

您应该在设置Realm时创建队列,并将其存储为执行安装的类的属性.

推荐阅读
手机用户2402852307
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有