【问题标题】:Modify Realm objects in Array without committing?在不提交的情况下修改 Array 中的 Realm 对象?
【发布时间】:2018-03-22 18:35:09
【问题描述】:

我正在更新一个 Realm 对象数组:

for offer in offers {
     if(offer.isReward == isReward){
        offer.isSeen = true
     }
}

但它抛出了一个错误:

Attempting to modify object outside of a write transaction - call beginWriteTransaction on an RLMRealm instance first.

我知道我可以这样做:

for offer in offers {
  if(offer.isReward == isReward){
      try! offer.realm?.write {
          offer.isSeen = true
      }
  }
}

在我对数组中的所有元素进行更改并提交整个数组之前,我是否可以推迟对 Realm 的写入?为每个需要更改的对象设置一个写事务似乎效率低下。

我最初的计划是修改物品并批量更新

 try realm.write {
     realm.add(offers, update: true)
 }

【问题讨论】:

    标签: ios swift realm


    【解决方案1】:

    对托管领域对象的所有更改都需要在写入事务中发生。您不能修改托管对象,然后再将更改写入 Realm,因为托管对象“永远不会离开”Realm,因此您对其所做的任何更改都会立即保存。

    在没有看到有关您的代码的更多上下文的情况下,我无法为您提供具体的实现,但总的来说(至少)有两种方法可以解决这个问题。

    首先,您始终可以创建托管对象的副本,然后逐个修改这些副本的值,完成后,在单个写入事务中从其副本中更新所有托管对象。但是,这需要在内存中存储两倍的对象,因此这不是最佳解决方案。

    第二种解决方案更优化,但仅适用于某些场景。您可以简单地将您当前拥有的整个代码包装在写入事务中,并遍历写入事务中的托管对象。这样,您只使用一个事务,但更新所有托管对象而不复制它们。但是,您不应该在写入事务中执行计算量大的过程,因此如果您在更新对象时需要执行长期任务,这也不是最佳解决方案。

    没有单一的写事务的好方法。在单个事务中更新的对象数量和使用多个事务更新少量对象之间需要权衡取舍。

    【讨论】:

    • 好答案。关于复制的更多信息:here an issue,试图找出将 Realm 对象深度复制到自身类型的方法,最后以一些有用的扩展结束。
    【解决方案2】:

    如果您保留realm 本身的实例,请调用beginWrite(),执行您的更改循环,然后commitWrite()

    let realm = try! Realm()
    //let offers = realm.... look up your objects
    realm.beginWrite()
    for offer in offers {
         if(offer.isReward == isReward){
            offer.isSeen = true
         }
    }
    try! realm.commitWrite()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-01
      • 2015-11-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-15
      • 2021-06-17
      • 2021-08-06
      相关资源
      最近更新 更多