【问题标题】:Uncaught RLMException when accessing Realm from Singleton从 Singleton 访问 Realm 时未捕获的 RLMException
【发布时间】:2017-03-22 14:05:24
【问题描述】:

这不是重复的问题,请继续阅读!

当我在 DispatchQueue 中使用 RealmBackend 单例时,我收到“'RLMException',原因:'从错误线程访问的领域'”错误消息。

这是我的课:

class RealmBackend {

    static let shared = RealmBackend()
    var realm = try? Realm()
}

其中有像addObject() 这样的函数正在访问realm.commitWrite()realm.beginWrite() 函数。

现在我用 DispatchQueue.main.sync 从回调 (UIRefreshControl) 调用 addObject 函数,因为我假设 Realm 对象是在 main 线程上创建的(我在 Github 上的某个地方读到你需要用于实例化和访问Realm() 值的相同线程)。

正如我之前所说,我总是收到这个RLMException,有人遇到过同样的问题吗?

【问题讨论】:

  • 那是因为你需要创建调度队列的后台线程的Realm实例才能在调度队列的后台线程上使用它....也建议把它放在显式的自动释放池中。
  • @EpicPandaForce 您能否在答案中发布一个小代码示例?我也尝试过(在我的单例的 privat init 中),但它给了我奇怪的错误。
  • 如果还期望在主线程上使用该实例,那么仅在后台线程上创建 Realm 实例是不够的。您需要确保使用单独的 Realm 实例;每个线程一个。我在下面的答案中概述了它的工作原理。 :)

标签: swift multithreading realm


【解决方案1】:

Realm 实例是线程受限的,这意味着它们只能在创建它们的线程上工作。如果你尝试在线程之间传递一个实例,你会得到你看到的不正确的线程异常。这是为了保证 Realm 的 ACID 合规性而设计的。

坚持对Realm 实例的硬引用没有多大意义,尤其是在单例对象中。一旦为特定线程创建了Realm 实例,Realm 将在内部保留该引用,并且如果您尝试创建一个具有相同设置的新引用,它将简单地重新提供它。因此,多次调用Realm() 的开销很小。

如果您需要使用与默认 Realm 不同的配置的 Realm 实例,Configuration 对象是线程安全的,因此您可以简单地存储一个对它的引用,并在任何时候将其传递给 Realm()需要它。

class RealmBackend {

    static let shared = RealmBackend()

    // A Configuration for a Realm in the caches directory
    let cacheConfiguration = Realm.Configuration(
                     fileURL: URL(fileURLWithPath: /* Path to the Realm in Caches */),
                     readOnly: true)

    func addObject() {
        let cacheRealm = try! Realm(configuration: cacheConfiguration)
        // ... add object to cacheRealm
    }

    func getObject() -> Object {
        let cacheRealm = try! Realm(configuration: cacheConfiguration)
        let object = realm.objects(Object.self).first
        return object
    }
}

在这种情况下,由于 Realm 是按需创建的,因此即使在单独的线程上调用单例方法,Realm 在内部也能够提供正确的实例。

【讨论】:

  • 我的荣幸!很高兴我能帮助你! :)
  • 我得到了同样的错误,我没有使用这个缓存配置,但在每个函数中我都在初始化 Realm let realm = try? Realm()
  • 不仅仅是Realm 实例;从Realm 派生的任何对象(即ObjectResults 等)都需要来自同一个线程。您可以在 Xcode 中设置异常断点,以确定导致崩溃的确切代码行:stackoverflow.com/questions/17802662/…
猜你喜欢
  • 2016-08-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-27
  • 2016-04-15
  • 1970-01-01
  • 2010-12-02
  • 2023-03-25
相关资源
最近更新 更多