Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the correct way to use realm in an autoreleasepool?

This is what the documentation has to say about accessing a realm using GCD:

"You should use an explicit autorelease pool when accessing a Realm from a dispatch queue."

Documentation

I have used this practice in my app but I am suddenly seeing the following message in my console: "RLMRealm instance was deallocated during a write transaction".

It is not throwing an error, it is just silently printing it to the console. Nothing is written to the database.

I found this issue on github that seems very similar.

My question is now: What practice should I use? The one used in the Realm documentation or the answer found in the github issue?

Thanks for any clarification.

like image 711
fisher Avatar asked Dec 19 '16 09:12

fisher


1 Answers

GCD blocks manage their own @autorelease pools, but there's no guarantee when that will actually occur, and it may happen a fair amount of time after the block itself has completed (See this SO answer)

Realm maintains read-locks on all of its instances across threads (This is how it's possible to still read from Realm while a write transaction is open on another thread), so as a result, it's recommended to explicitly dealloc a Realm instance when you're done so that disk space can be reclaimed.

If you don't use an @autoreleasepool, nothing too bad will happen; just the size of the Realm file on disk will increase.

Best practice is to use an @autoreleasepool block, and to ensure that all of your write transactions are committed inside that block.

@autoreleasepool {
    let realm = try! Realm()
    try! realm.write {
        // ... perform changes
    }
}

It's usually recommended to use realm.write over beginWrite()/commitWrite() since it lets you safely perform transactions without forgetting to commit, and also provides some extra error handling.

The problem with the issue on GitHub was that there was a logic path that would cause the @autoreleasepool to exit before the write transaction had been committed. In this case, you need to review your code logic and make sure you haven't got anything similar.

like image 177
TiM Avatar answered Oct 02 '22 07:10

TiM