Lazy undo for Arrays

  • Using a subclass of NSArrayController for a NSTableView and wishing to
    do the usual litany of edits on the array list, I was having trouble
    wrapping my brain around all the possible undo scenarios.  Being a strong
    believer in using the same hammer to pound most nails, I came up with a
    unified undo approach that may not be optimal, but seems to work quite well,
    with one exception.  For some reason, my attempt at restoring the undo
    selection isn't working although it works for do/redo.

        It works by first making two copies of the array which you want to edit
    -- editArray and undoArray.  You edit editArray, then replace all the
    elements of the original array with those from editArray.  For undo, you
    replace all the original array elements with undoArray's elements.  I also
    pass the the old and new selections.  Here is what I did:

    @interface RTPArrayController : NSArrayController

        NSArray* undoArray;    //    Temp array for undo memory
        NSMutableArray* editArray;    //    Temp array to edit
        //  Note that these could have been locals for each method.  It just
    seemed more efficient to use ivars and the "prepareForUndoRedo" method.

    @implementation RTPArrayController


    - (void) prepareForUndoRedo
        NSMutableArray* arrayToChange = (NSMutableArray*)[self arrangedObjects];
        [self setUndoArray:[arrayToChange copy]];    //    Temp array for undo
        [self setEditArray:[arrayToChange mutableCopy]];    //    Temp array
    which we will edit

    - (void)changeArray:(NSArray*)changeArray
        NSUndoManager* undo = [tableView undoManager];  //  There is an outlet
    to tableView.
        [[undo prepareWithInvocationTarget:self]changeArray:memArray
        [undo setActionName:name];

        NSArray* arrayToChange = (NSArray*)[self arrangedObjects];
        [self removeObjects:arrayToChange];    //    Clear the array
        [self addObjects:changeArray];    //    Load new array
        [self setSelectionIndexes:newSelects];

        //    This is a prototype for undoable methods
    - (void)whateverEditMethod {
        [self prepareForUndoRedo];
        NSIndexSet* oldSelects = [self selectionIndexes];

        //    Do your worst to the editArray here

        NSIndexSet* newSelects = whatever;  //    New selections

        [self changeArray:editArray
previous month september 2007 next month
          1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Go to today