iOS file i/o best practice - ios

I am writing a iOS app that contains an array of NSDictionary objects these objects can be added/removed and edited by the user. The array is stored in a plist and loaded at runtime. I am wondering what the best practice would be on when to store the data into the plist i.e. should I do it every time the array changes or only when the app is terminated or goes in the background?

Doing it only when the app is terminated or goes to the background would be fine. If you have very large data, you may want to do it periodically because you only get so much time to "wrap things up" when the application is about to terminate. But will small data, it is just fine to write on terminate or when entering background.

It would help to have more information about the nature of your app, but I would save on background/terminiation. It seems inefficient to be saving every couple seconds if there isn't a need for it.
I would save as often as necessary for your app to function properly, no more and no less.

Related

Is userDefaults any worse performance than writing to a file? And how bad is that?

I'm receiving crash reports in Xcode that so far aren't very helpful. I've updated my app to detect when the app crashes, and ask the user to tell us what happened when the app crashed.
That said, I'm toying with storing off the last method 'entered' in userDefaults so that I can include that in their email.... but don't want to slow the app to a crawl. Because I'm trying to detect what started before a crash, I'd need to do a synchronize too... or I'll lose the update. At the start of each method, I'd need to write out the class & method to userDefaults & sync. I'd be overwriting the same "LastMethod" key each time, not keeping multiple values.
Thoughts or alternatives?
I save a couple of Int and Double arrays to userDefaults every second (autosave function) in my game and on iphone 11 works great.
Launch of the application takes a second so it can be skipped.
UserDefaults can save integers, booleans, strings, arrays, dictionaries, dates and more, but you should be careful not to save too much data because it will slow the launch of your app. So you should not save big data
There is also synchronize() method to force your data to save but Apple says we should not use.

Delete data when app is killed in the background.

I have an app where I am saving data but when the app is killed in the background I have to delete all the saved data.
I tried using this method:
- (void)applicationWillTerminate:(UIApplication *)application
But its not working. Can someone please suggest me how to do that?
Not sure why you need to wipe the data on terminate specifically, but here is something to consider:
Another way to handle this type of situation when apps write data that may be incomplete when they are forced to quit, is that they write out a flag when the data is known to be good.
That way, if the app exits normally, the data will be written and the flag will be written.
If the app is forced to quit, the flag will not get written by nature of the forced quit.
THEN, when the app starts it can look for the flag. If the flag isn't there, the app knows that any data is incomplete and can discard it (delete it) and start over.
Hope this helps.
applicationWillTerminate: is basically never called and you should no longer rely on it.
The app is not given any callback when it is killed so you can't do anything. You need to decide on a different approach based on the actual user requirement. This may involve encryption / not holding certain data on disk (only ever in memory) / etc...
I know, I'm super late to the party but, if you can live with data "sticking around" until the next app launch you can delete/clear data in application(_:didFinishLaunchingWithOptions).

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.

CoreData - when do I save?

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.

What actions are required when your app get an applicationWillResignActive call?

This question io3->ios4 upgrade said to support applicationWillResignActive. While implementing this call, I also implemented applicationDidEnterBackground and applicationWillEnterForeground. However, I found that my app would crash. After some debugging on the simulator I determined that I needed to reinitialize a key data structure in applicationWillEnterForeground. So my question is how would I have known that from reading the documentation? (In fact, I may be doing the wrong thing and just so happened to get it working again.) Is there an exact description of what to do when these methods are called?
Thanks.
The only things you should do when supporting multitasking, is saving the state of your app when it enters the background, and reload it when it becomes active. (If you generate a new template in Xcode, you'll see this.)
Saving state means writing any user preferences or data to disk. Reloading the state involves reading saved preferences and data, recreating any in memory data structures that might need it (like in your example you gave).
In most circumstances, there's little else you need to do. The only thing that would crash your app that is unique to multitasking would be trying to run code in the background for longer than the allotted amount of time, (which is 10 minutes.) Otherwise, it sounds like you have got other problems with your code.

Resources