Search code examples
iosswiftrealm

Modify Realm objects in Array without committing?


I am updating an array of Realm objects:

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

but it is throwing an error:

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

I know I can get it working by doing:

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

Is there anyway I can hold off on the writing to Realm until I have made changes to all the elements in the array and just commit the entire array? It seems inefficient to have a write transaction for each object that needs to be changed.

My original plan was to modify the items and bulk update

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

Solution

  • All changes to managed Realm objects need to happen inside a write transaction. You cannot modify a managed object, then later write the change to Realm, since a managed object "never leaves" the Realm and hence any changes you make to it will be saved immediately.

    Without seeing more context about your code I cannot give you a specific implementation, but in general there are (at least) two ways to get around this issue.

    Firstly, you can always create copies of managed objects, then modify the values of these copies one-by-one and once you're done update all managed objects from their copies in a single write transaction. However, this would require storing twice the objects in memory, so it's not an optimal solution.

    The second solution is more optimal, but only works in certain scenarios. You can simply wrap the whole code you currently have in a write transaction and iterate through the managed objects inside the write transaction. This way, you only use a single transaction, but update all managed objects without making copies of them. However, you shouldn't be doing computationally expensive processes in a write transaction, so in case you need to perform long-lasting tasks when updating your objects, this isn't an optimal solution either.

    There's no single good way of doing write transactions. There's a trade-off between the number of objects being updated in a single transaction and using several transactions to update a small number of objects.