适当的 Realm 使用模式/最佳实践?

79

我们正在将一个项目转换为使用Realm。到目前为止,我们对Realm Browser(非常方便!)印象深刻。

因此,在继续之前,我们想要制定一些具体的使用模式,出现了一些问题。我们的应用程序是高度多线程的(API调用、动画等),因此在阅读问题时,请牢记Realm实例当前不能跨线程访问。

  • 我们应该担心反复创建Realm实例吗?这会带来什么开销?
  • 我们是否应该保留ViewControllers或Singletons中的Realm实例以供重复使用?我们尝试过这样做,但有时从不同的线程访问实例,因此我们不得不每次都创建一个新的实例。
  • 当访问Realm实例上的关系属性时,读取的数据是否会被保留在内存中,还是每次都从磁盘读取?我们是否需要担心由于深层关系访问而变得太大的保留Realm实例?
  • 何时需要刷新Realm实例?我注意到当我在Realm浏览器中进行更改时,它们会在保留的Realm中反映出来,而无需调用refresh。
    • 根据文档,似乎每个Realm上都有一个自动刷新属性可以导致这种情况。
  • 访问Object上的realm属性是否是不好的实践?我们在写入Realm时使用了它,如果使用对象的函数没有创建对象或Realm(当然是在同一线程上)。

例如...

func saveStuff(thingToUpdate: Object?) {
   if let thingToUpdate = thingToUpdate, let realm = thingToUpdate.realm {
       realm.write {
           thingToUpdate.name = "lionpants"
       }
   }    
}

提前感谢您,期待您的答案。 :D

1个回答

90

(声明:我曾经在 Realm 工作,但现在已经离开了。我仍然乐意帮忙!) 非常感谢!很高兴听到您喜欢使用 Realm!

多个 Realm 实例 - 您无需担心这个问题!每当第一次在某个线程上实例化一个 Realm 文件对象时,将创建该对象,并且每次尝试在之后的任何时间实例化它时,都将返回同一个对象。

保留 Realm 实例 - 根据第一个要点,不,您不需要担心是否要在其他对象内持有 Realm 引用。由于 Realm 在内部跟踪其 Realm 文件对象并返回相同的对象,因此如果不这样做也不会受到惩罚。尽管如此,如果在您的对象中始终保留对 Realm 对象的永久引用可以简化代码复杂性,则可以继续使用它。

访问 Realm 关系属性 - 严格来说,Realm 文件中的数据并不是从磁盘上复制过来(就像普通的 ORM 会做的那样);它更多地使用内存映射直接将数据从磁盘引用到您的内存属性中。因此,不,您不需要担心 Realm 文件在内存中过大。

自动刷新 仅针对主线程上的 Realm 文件对象,默认启用自动刷新。必须手动启用其他线程上的 Realm 文件对象的自动刷新,或者可以选择使用 refresh 方法手动刷新它们。

编辑: 我纠正了!所有多个线程上的 Realm 文件对象默认都启用autorefresh。当启用autorefresh时,在当前运行循环的迭代完成之前,您唯一需要调用refresh的时间是如果您需要将对 Realm 文件所做的更改反映在其他引用中。

引用对象的 Realm 引用绝对不是不好的做法!我实际上更喜欢在使用Realm的个人应用程序中这样做,以提供适当的上下文,因为这样做通常更容易,并在代码中提供对象和其父级Realm文件之间更强的可视化联系。 (哈哈,是的,如果出现线程问题,您可能甚至会在达到“write”点之前发现它)。希望这有所帮助!如果需要任何澄清,请告诉我!


太棒了!感谢您的超快速响应。我们会确保在出现任何问题时发布更多的问题!关于自动刷新仅默认启用在主线程上的观点,也应该添加到文档中。 :) - lionpants
4
完全没有问题!非常感谢!啊,实际上我改变了想法。我刚才回去查看代码以确认,发现自动刷新现在在所有线程中都启用了。我已更新我的答案以反映这一点。 - TiM
我对这个内存异常问题感到非常紧张,似乎无法解决,用户在生产应用中也抱怨了很多。 - Eenvincible
针对iOS平台,您能否在Realm的GitHub存储库上创建一个问题,并提供更多信息?https://github.com/realm/realm-cocoa - TiM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接