CoreData - when do I save? - ios

I understand how to use CoreData, but I'm confused when it's best to save the data. When they press the home button? On every interaction in case the app crashes?

The reason why saving data is a separate call is so that you can batch multiple smaller changes that comprise a larger operation and save all at once, rather than saving at each step along the way.
You should save the data after each atomic operation, and never have committed data sitting only in memory for any significant period of time.
Each time the user commits a change to the data, they will expect the data to be there the next time they run the app, so it's your job to make sure it's there.
After your user submits a change to the data, your app is likely going to be waiting for the user do something else anyway, so save the data while the user decides what to do next.
If you wait to save data in the applicationDidEnterBackground, there is no guarantee that it will ever be called.
Obviously, not all data is critical, for example, data that a user has entered on a form, but hasn't submitted, is not critical. However, any submitted data is critical.

I don't think its a good idea to save on every interaction(Honestly your App shouldn't be able to crash on "every" Interaction ;) ).
I only save in my app in
- (void)applicationDidEnterBackground:(UIApplication *)application
In fact you are right regarding crashes. But what if an invalid Data causes the crash? So you will reload in the worst case the data so that it crashes every time.
But to be honest that is just an educated guess - I think it depends on how sensitive your Data/App is
edit: This answer provides a similar opinion Saving Core Data Context before Crashing
But there's is a really good point I missed:
you should save whenever the user performs critical operations

If you save in the background, you can do it very often without harming UX much. Remember though that you probably need to update you UI and that will have its impact (merge after save to main will be done on the main thread).
Keep you saves small (small number of objects) so not to stall the main thread.
it is very dependant on your CoreData stack architecture.
You will want to save on critical moments like entering background, or user important data/demand.

Related

Remove Core Data Support From An App On The App Store

I have an app on the App Store, and it is getting a decent amount of use. I'm doing things differently as I release updates, and want to completely remove core data from the application. How exactly do I go about doing that in the next released update?
Do I simply remove all the core data code in the AppDelegate file, and remove the data model file?
I want to be certain no units will crash as the new update is released.
Option 1: just ignore it
This is by far the easiest solution. Just leave the core data files on the user devices and they will just forever take up space for the user. If the amount of data is small (less than 50mb), and the data stored in them has either already been transitioned or doesn't need to be, then this is a good option. You can remove all reference to core data from your app.
Option 2: delete it in the background
You can delete it in the background when the app first runs. Make a background context, fetch all objects, delete them, and save. When done mark that it is done in NSUserDefaults and don't do it again. If the amount of objects is very large it might require more complex code of batching the fetches and deletes. You need to retain at least the core data model, and possibly much more, in order for the delete to work.
Option 3: transition the data
This is the hardest option because transition the data can take time, and if it takes too long iOS will force quit your app. So first present a view controller explaining the user what is happening - and perhaps a progress indicator. Then fetch the data in batches, save to you new store, delete it, and update your progress indicator. When all the transition is done, then update your view controller. Here you might need to retain a large amount of core-data code just to deal with this transition.

When to update my persistent storage (core data)?

I have a NSObject that I manipulate quite a lot, as the user changes different things. It seems a bit crazy to update the core data every single time there is a change. It would require a lot of coding just for one little change in these different places.
When should I update the core data if I want my stuff to persist? Is it a bad idea to only update it before the app closes?
Thanks
When should I update the core data if I want my stuff to persist?
Basically, you save whenever you feel that the changes are significant enough and should be saved.
Is it a bad idea to only update it before the app closes?
If the changes are important and you don't want them to get lost, what do you think happens in case the app crashes or terminates, battery dies etc..? Well, all the changes get lost if you havn't saved it.
It seems a bit crazy to update the core data every single time there
is a change.
Well, the application can not magically know what is important to you that should be saved and what would not. This is how it works generally for everything.
So basically, thats the guideline, the rest is up to you.

Ideal time to invalidate cached data in an iOS app

So I'm working on an iOS app which uses Core Data as a local, offline store for data stored on a remote server. Think like the way Mail.app keeps your most recent n messages. Now right now the app quite naively stores all of this data without deleting any of the old data.
My question is this: what's the best time in an iOS app's lifecycle to take care of tasks like removing cached data? I already know how I'm going to delete this old data, but doing so is an expensive operation. So what I want to know is when the best time to perform this sort of expensive operation is.
If it is not too much trouble, then doing so when the application goes into the background would be a nice time to do it. If it takes around 10 seconds or more, though, be sure to set up a background task to allow you to run for a bit more time.
You can run this operation in background with GCD or NSOperationQueue. I would do it after I get new data from server, then delete old cache, and build new one. If you move expensive operation to background (threads, block, NSOperation, or what ever you prefer) then it better to use child NSMagaedObjects for synchronization.

Saving Core Data Context before Crashing

For example if we hit "Stop" in XCode, it will close the app, mimicking the crash behaviour.
But if my Core Data Context hasn't been saved, when I go back, the data won't be there.
Are there any workaround for this?
Should I save the context every time a big operation is finished?
Thanks.
Based on my experience you should decide the right granularity when you use Core Data save mechanism.
IMHO (maybe someone else could have different opinions) there is no standard to follow. My rule of thumb is taking into considerations two different aspects. The user and performances.
In the first case, you should save whenever the user performs critical operations. e.g. the user has inserted a lot of values in a form and hence he will expect to not insert them again. Regarding the second aspect, save operations could impact the performance of your app. If you frequently write changes to disk the app will be less responsive. On the contrary having so many objects in memory could led to memory warning (those will cause Core Data to take specific behaviors).
A tradeoff could be using background operations to save changes or take advantage of new Core Data API. Obviously, previous rules still remain valid.

Best Core Data save strategy (when to save data to disk)

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:
save context at the end of every change
save context only on app's exit (like in Apple's samples)
save context on app's exit, going to background or becoming not active (incoming phone call for example)
add timer to save context from time to time if it has any changes
call specially prepared delayed save routine which will gather together calls to save context to make sure they don't fire too often
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?
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/
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.
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".
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.

Resources