Reputation: 9044
NSUndoManager
must only be used in a child NSManagedObjectContext
(when used with Core Data). This is because the UIManagedDocument
may auto-save at any point in time, after which an undo
will have no effect. Therefore there is no point using NSUndoManager
to just achieve save/cancel functionality, since a child context will give you the same result.
Bit sad really, because NSUndoManager
is a lot easier to implement than a child context (for the latter I have to call existingObjectWithID
to copy objects from the parent to the child - painful). Personally I would have thought the document should not auto-save if groupingLevel != 0
. Rant finished.
I have a table view controller that loads data using Core Data into a UIManagedDocument
. It segues to a view controller to edit each row in the table. In that view controller I have cancel and save buttons. I am implementing the cancel capability using NSUndoManager
through a category on my NSManaged
object (self.list
below).
- (void)viewDidLoad
{
[super viewDidLoad];
[self.list beginEdit];
}
- (IBAction)cancel:(id)sender
{
[self.list cancelEdit];
[self close];
}
- (IBAction)save:(id)sender
{
[self.list endEdit];
[self close];
}
The category implements beginEdit
, endEdit
and cancelEdit
which is intended to handle the NSUndoManager stuff. In the code below, useUndo
is a constant that I set to NO or YES to see the impact of using NSUndoManager.
- (void)beginEdit
{
if (useUndo)
{
NSUndoManager *undoManager = [[NSUndoManager alloc] init];
self.managedObjectContext.undoManager = undoManager;
[undoManager beginUndoGrouping];
}
}
- (void)endEdit
{
[self.managedObjectContext save:nil];
if (useUndo)
{
NSUndoManager *undoManager = self.managedObjectContext.undoManager;
[undoManager endUndoGrouping];
self.managedObjectContext.undoManager = nil;
}
}
- (void)cancelEdit
{
if (useUndo)
{
NSUndoManager *undoManager = self.managedObjectContext.undoManager;
[undoManager endUndoGrouping];
[undoManager undo];
}
}
I can see the Core Data debug messages showing it is committing the changes if I save an object and click the Home button when useUndo = NO
. However, with useUndo = YES
, it does not auto-save when I click on the Home button. I have waited a couple of minutes, and it still doesn't autosave. Is there some way I can force an auto-save?
Can anybody explain why using undoManager causes this change in behaviour?
I suspect either I am going about this the wrong way, or have some simple problem in the code. Any help would be appreciated.
Upvotes: 3
Views: 892
Reputation: 2725
I'm not sure if it's correct but other answers on stackoverflow have mentioned that an NSUndoManager clears the undo stack when the context saves. That means that using an undo manager with auto-save would at most be useful for a couple of seconds (whatever the auto-save interval is). There might be a connection there, I'm trying to find out more...
Upvotes: 1