views:

391

answers:

2

In the generated code for core data stack, a save on managedObjectContext is called in applicationWillTerminate method. This is to take care of all unsaved objects in the context before exit.

This has an unwanted side effect of saving any temporary objects as well. (This problem is visible in apple sample codes as well. If you click on + to add new Recipe in Recipe sample code, and then press Home button to terminate the app, a half done Recipe object is visible when you start the app next time).

What is the preferred design pattern for handling this issue? I could think of the following.

  1. Use a different scratchpad managedObjectContext for temporary objects and when you decide to really Save, then push a copy in the main managedObjectContext. Call save only on main managedObjectContext in applicationWillTerminate. (Is there any easy and fast way to move an object from one managedObjectContext to another apart from creating a copy manually in the new context?)
  2. Remove save from applicationWillTerminate, but ensure that all Objects are saved immediately after changes are made. (This may not easy all the time, I have a Tabbed application, a user may have initiated editing operations at the same time).

Let me know if there is a better way to handle this.

A: 

Solution 1 entails fully copying objects. However, copying an object is tricky. Properties can be handled easily, but relationships are subtle. To copy relationships (a deep copy, not a shallow one) you need a recursive procedure, in which you always take care that you are not copying again the same object over and over again if ever met again during the recursion step.

Solution 2 may be easier to implement depending on your application logic and, as you noted, GUI.

There is a third possibility to handle correctly temporary objects as follows. Add a boolean property to the entity associated to your objects which keeps track of the object status (temporary or not). Then, using the NSManagedObjectContext methods

- (NSSet *)insertedObjects

you simply enumerate the set of objects and, depending on the value of the boolean flag either save or delete the object.

Note that this may be of course quite expensive depending on the number of objects.

unforgiven
You are right about Solution 1. It can be tricky. The 3rd solution combined with Solution 2 should work fine for me. I tend to Save as soon as the user commit changes. Its only for those scenarios where the user may be in the middle of adding a new instance and then decides to terminate the app. A check for insertedObjects would work there as I do not expect too many temp objects either. Thanks for the suggestion.
siasl
Added new logic, worked like a charm ...
siasl
Glad to know ;-)
unforgiven
A: 

Solution 1 does not entail copying objects. The pattern is illustrated in the CoreDataBooks example. You can create new objects in a second context, then fault them into the main context either directly (using objectWithID:) or (as shown and explained in the example) by observing NSManagedObjectContextObjectsDidChangeNotification and merging the changes into your main context.

mmalc