views:

511

answers:

1

In my Core Data model, I've got a relationship called listItems which links to several listItem entities, each with a stringValue attribute. I've created a control which is essentially a list of NSTextFields, one for each list item. The control is bound to listItems properly, and I've set it up so that pressing the return key creates a new field directly under the currently-edited one and changes the focus to the new field. So, essentially, to add a new item, the user presses Return.

Likewise, if the user ends editing and the currently-edited field is empty, the field is removed (as in, empty fields only appear during "edit mode", so to speak). This works pretty well. Basically, in my listItem NSManagedObject subclass, I do the following:

// Don't allow nil values
if (!value && [[self.recipe ingredients] count] > 1) {
 for (EAIngredientRef *ingredient in [self.recipe ingredients]) {
  if ([[ingredient sortIndex] integerValue] > [[self sortIndex] integerValue]) {
   [ingredient setSortIndex:[NSNumber numberWithInteger:([[ingredient sortIndex] integerValue]-1)]];
        }
    }
    [[self managedObjectContext] deleteObject:self];
    return;
}

// Code to handle if it is a real value

The problem I am encountering is that each time a row is deleted this way, it registers with the undoManager. Thus, if I edit a row, press Return (which creates a new row), and click away to end editing, the row disappears. However, if I then undo, the empty field reappears. My goal is to have delete operations involving empty fields be ignored by the undoManager.

How would I go about this? I've tried using [[[self managedObjectContext] undoManager] disableUndoRegistration] and the associated enableUndoRegistration in several spots (such as -didTurnIntoFault, but I suspect that the undo registration might be happening prior to that method)

+4  A: 

If you dive more deeply into the Core Data docs, you'll find this tidbit hidden away:

[[self managedObjectContext] processPendingChanges];
[[[self managedObjectContext] undoManager] disableUndoRegistration];
// Do your work
[[self managedObjectContext] processPendingChanges];
[[[self managedObjectContext] undoManager] enableUndoRegistration];

Changes are not registered with the undo manager normally until the end of the event loop, and so were being registered after you'd turned undo registration back on. The above forces it to occur when you want.

Mike Abdullah