Reputation: 1797
Based on your experience, for an iOS app which uses only one main-thread only NSManagedObjectContext, what is the best way to persist user settings and cached data from server to disk with respect to reliability and performance?
I see next options:
Currently we use the 1st option, so I can say that the reliability of it is very good, the data is saved even after Xcode terminate the app during debug session, but performance may suffer when app become more and more complex, esp. when changes to DB can happen at any moment of the app's flow due to async loading of data from server.
On the other side saving at certain events of the app (exit, going to background etc) will give the best performance, but can you say from your experience that it is enough to make sure that user will not loose the data?
Upvotes: 21
Views: 7111
Reputation: 101
According to Apple documentation "It is recommended that you save user data at appropriate points throughout the execution of your app, usually in response to specific actions. For example, save data when the user dismisses a data entry screen. Do not rely on specific app state transitions to save all of your app’s critical data".
Upvotes: 4
Reputation: 300
I used to save context on every changes but the performance is really not that good. Currently I'm saving the context on the end of the fetching data function. The performance is like 4 times better. Just make sure you have [context lock]
and [context unlock]
at the beginning and the end of the function if you plan to call the function async in background threads.
Upvotes: 3
Reputation: 6082
I think you should save often, because it's more reliable (you won't lost data if the app crashes) and you can save free up memory occupied by modified but unused objects.
At the same moment you don't want to overwhelm db with your save requests.
My suggestion is to expose two methods in interface file and choose which one you want to call depending on the situation you have.
- (void)save {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(save) object:nil];
[_storage save:nil];
}
- (void)setNeedsSave {
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(save) object:nil];
[self performSelector:@selector(save) withObject:nil afterDelay:1.0];
}
Also, have you considered using second managed object context with private queue? You can set it up as a parent context and save / fetch data in background: http://www.cocoanetics.com/2012/07/multi-context-coredata/
Upvotes: 11
Reputation: 2689
Saving the context in the UIApplicationDelegate
methods applicationDidEnterBackground:
and applicationWillTerminate:
has always been fine for me. I also save in special circumstances like a big data import or something similar.
Upvotes: 5