I have a memory-intensive iOS app and I'm working on making sure that memory usage does not build up over time. My app has a "main" context that lives for the lifetime of the app, with other smaller contexts being spawned occasionally for background tasks.
One thing I have noticed is that NSManagedObjects appear to remain registered in the main context long-term and the only way to truly reclaim all the memory associated with pulling the objects from the DB is to call [NSManagedObjectContext reset]
.
This of course results in a nice drop in memory usage as all the registered objects from recently closed list views are properly ejected from memory, however it is annoying because you have just invalidated every object that was registered in that context that you still have a reference to (i.e. objects that are refered to by views that are still open), and you now need to re-fetch all the these objects from the database to avoid exceptions for accessing an invalidated object.
Is this the only way of flushing out the registered object set from an NSManagedObjectContext, or is there a better way that successfully ejects all the registered objects you no longer have references to, but doesn't invalidate all the NSManagedObjects that are still alive?
NSManagedObjectContext
has an internal row cache, and the only way you can clear that out is by resetting the context. If you're actually experiencing memory issues, a few things that may help are:
A
that's referenced by a relationship from some other managed object B
, then object A
will remain in memory even if you've released all references to it. It won't actually be deallocated until object B
is deallocated or re-faulted, because it will still be retained by B
.refreshObject:mergeChanges:
on the MOC for objects you aren't currently using, with the second argument set to NO
. That re-faults the object, i.e. makes the object go back to the initial "fault" state, unloading its property values and relationships. With A
and B
from before, re-faulting B
would release the relationship to A
. Keep in mind this will lose any unsaved changes on B
, so make sure you've saved first if necessary.reset
on the MOC is basically the nuclear option when it comes to Core Data memory management. It's extremely effective but as you've found can be very dangerous. It's best avoided unless you already aren't using any objects loaded from the MOC.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With