Cancelling edits: NSUndoManager or separate NSManagedObjectContext for editing?
I have a View Controller that manages a view which is always shown in editing mode. The view is essentially a table view similar to that of a contact's details in Apple's Contacts app. The model underneath my view is represented by a 2-level object graph comprised of a root entity - call it R
- having a to-many relationship to a child entity C
. Now, R
is a large object (it has 20+ attributes, all editable but non-mandatory). By default, R
has n
children (n
being a configurable value), but child objects can be added and removed to/from R
's collection via my editing view and C
's attributes can be edited as well. Note that C
entities include attributes for image meta-data, so there may be images picked and associated with the model while editing.
Edits on R
and its children are per开发者_开发知识库formed via the main table view form, as well as from "secondary" views to which I navigate (back and forth) in order to collect the required information, depending on the case.
My question is, how would you implement a "Cancel all edits" in this situation, i.e. how should I isolate all my edits to easily revert to the state prior to editing? Using a NSUndoManager
with my main NSManagedObjectContext
? Having a separate NSManagedObjectContext
for editing? What would be the trade-offs for each?
I don't care for redo
. I am looking for an idea/solution that would strike a balance between the amount of memory used while editing vs. the ability to save the user's data if the app is interrupted while editing.
Thank you for all your ideas.
I would advise against a design that has the same edit function in two different views. Each view should represent objects of an different entity/class of the data model and should therefore have different editors and undo management.
The contact app shows how this is done. You can delete an entire contact in the master tableview and individual contact attributes in detail view. The changes in each view are committed when the view disappears. Such a setup not only makes undo management much easier but makes it much easier for the user to understand exactly what changes they are making.
If you want to stick to your original design, I would suggest keeping the undo stack of the master tableview until the master unloads completely i.e. not when the detail view loads.
I concluded here that for NSUndoManager
to work properly with Core Data, it must be done in a child context. Since a child context gives you "Cancel all edits" capability, you don't also need NSUndoManager
. Therefore, every cancel-able View Controller should do its work in a child context This means, for example, controller A would use a child of the document's context, and if it segues to controller B, that would use a child of A's context (child of child of document context). If the users presses Save, the context is saved which automatically propagates the changes up to the parent. If the users presses Cancel, the context is discarded thereby ignoring the changes. The only complication is with an iPad app where A and B might both be visible and the user presses Save on A (but this is probably just bad design).
精彩评论