We're reworking a big app from scratch with Swift and decided to try Realm instead of CoreData.
Right now I'm facing a small issue regarding the threading model to use.
My intention was to run all the reads and writes on the database on a background queue, so that the UI would not stutter too much. But as is turns out, Realm is not really prepared to work with dispatch queues, even if it is always the same, since iOS can dispatch code on a given queue on different threads in the same run.
So my question is: am I forced to run all reads and writes on the main thread with realm? Please note that every class in our persistence layer instantiates a reference to the realm at init() time, but init() is not guaranteed to be called from the same queue (since the startup process involves downloading plists, tars, uncompressing them, parsing XMLs, and storing things in the database, and this happens on multiple queues), so I cannot assume that a realm is safe to use at any given time.
Or am I getting everything completely wrong and I'm not supposed to keep a reference to the realm, bounding me to use it on the same thread, but just keep calling RLMRealm.defaultRealm() every time that I need to read or write something?
Thanks
Hi @vittoriom you are correct that you need to keep calling RLMRealm.defaultRealm() every time you are on a new thread. You can do reads and writes in background threads, you just can't pass RLMObjects/Realms between threads. One way people handle passing objects is by using primary keys. By fetching primary keys in a background thread, you can then send those over to the main thread and re-fetch for those objects there. For the most part Realm is fast so people haven't had too many issues doing it this way.
We are aware of the problem with doing long running operations on the main thread and are actively looking at different ways to handle threading and the passing of objects.
Hi @yoshyosh and thanks for the reply. I actually don't need to pass objects between threads since my persistence layer only outputs lightweight structs that can be easily passed around. Still, I'm not 100% sure when you say
You can do reads and writes in background threads
Since when I do that, I get something like "Realm is accessed from the wrong thread".
Do you mean that in order to do that, I just need to call RLMRealm.defaultRealm() before every read or write, instead of storing the RLMRealm into a property?
Exactly, everything should work fine if you do that :)
Thanks, I will give it a try! Feel free to close the issue if you want to clean the board :)
Awesome, just let us know if you run into any other issues!
wondering why 'objects cannot be shared between threads' limitation exists? Objects are allocated on heap and the heap memory is shared by all threads. It seems like the limitation is something to do with transactions. Could someone give more detailed explanation or point me to a place to read about this?
When you access the property of an object we proxy that to the database, so you are really not reading/writing the property on the heap but in the database directly. If two threads could update a property simultaneously, you would loose any guarantee of consistency. That's why a write transaction blocks all other write transactions to only allow one mutation at a time. Hope this helps.
BTW, it's much better to create a new issue and refer to the old in case of additional questions since closed issues are normally not monitored. Hope this helps?
Thanks! That makes sense. will create new issue if i have question in the future.
Most helpful comment
Hi @vittoriom you are correct that you need to keep calling
RLMRealm.defaultRealm()every time you are on a new thread. You can do reads and writes in background threads, you just can't pass RLMObjects/Realms between threads. One way people handle passing objects is by using primary keys. By fetching primary keys in a background thread, you can then send those over to the main thread and re-fetch for those objects there. For the most part Realm is fast so people haven't had too many issues doing it this way.We are aware of the problem with doing long running operations on the main thread and are actively looking at different ways to handle threading and the passing of objects.