views:

1635

answers:

2

Hi there,

If the user is currently in my edit view controller, I want to be able to save the changes when the user closes my app. To do this I am observing the UIApplicationWillTerminateNotification of the shared application. In my app delegate, I use the applicationWillTerminate: method to close things down and release all my core data contexts.

The problem I'm finding is that the applicationWillTerminate: method in the app delegate gets called before any observers react to the UIApplicationWillTerminateNotification notification. This means that my core data stack has been released and closed before my edit view controller gets a chance to save anything!

How is this usually overcome because I can't see a way!

Many thanks,

Michael

+2  A: 

Edit: The first (notification-based) approach probably won't work due to the inner workings of run loops and notifications.

If you want to stick with the notification-based architecture, you can actually post your own notifications from within applicationWillTerminate:. Simply create your own MyApplicationWillTerminate notification, then call postNotification: on [NSNotificationCenter defaultCenter]. Then have your edit controller register for instances of MyApplicationWillTerminate rather than the default UIApplicationWillTerminateNotification.

Another choice is to have your app delegate store an instance of your edit controller if it's visible, then in applicationWillTerminate: save the new info before releasing the Core Data context. This pollutes your app delegate with extra instance variables, though, so it may not be the optimal solution.

A last thought: why not have the app save whatever edits are being made as the user makes them? That way, you don't have to worry about the app closing halfway through editing a piece of info - the edits are already saved, and you can simply release the Core Data stuff as you already are. (This may not be appropriate for you; I really couldn't say without knowing more about your app structure and what data you're editing.)

Tim
+1 for saving drafts as the user makes their edits; time to do anything useful or complicated during termination is pretty limited.
Sixten Otto
Interesting point about saving edits as they happen. I might look into that. When you mention posting my own notifications, won't they get picked up on the next run loop and after the `applicationWillTerminate:` code has finished? As all the code will be on the same (main) thread.
Michael Waterfall
Michael: you're probably right - I realized this right after I posted my answer (now edited). You're probably best off saving edits as they happen and thus sidestepping this problem altogether.
Tim
I've just had a thought! I noticed that the edit view controller's `viewWillDisappear:` method gets called before the `applicationWillTerminate:` does. So I could save my drafts then! It's not a very complicated save, just a plist with a few bits of data so I think it would be fine performing the save on terminate. Any thoughts or possible downsides?
Michael Waterfall
You could, but remember that once the user presses the home button, Springboard gives your app a short period of time (around four or five seconds) to close itself or it will terminate the app for you. This looks like a frozen app and a crash to the user, which is not a good thing. Furthermore, even if you only take a second or two, you're giving the impression of a slowed-down device because of the delay between button push and home screen. So while you *can* do it, yes, ask yourself: *should* you do it, and can it be done quickly enough?
Tim
A: 

Not sure here, but does NSManagedObjectContext retain its store coordinator and object model? In that case, wouldn't it suffice to have your controller retain the managed object context?

Ole Begemann