How does undo/redo basically work on iPhone OS?

前端 未结 1 1638
不思量自难忘°
不思量自难忘° 2020-12-02 16:32

My app doesn\'t use Core Data yet. Is it true that I must use Core Data for undo/redo?

And: How does the user do the undo/redo? I\'ve never seen it in actio

相关标签:
1条回答
  • 2020-12-02 16:50

    iPhone OS 3.0 brought over the concept of NSUndoManager from the Mac, which is what enables undo on the iPhone. NSUndoManager maintains a stack of NSInvocations which are the opposite actions to any edits or other changes you make. For example,

    - (void)observeValueForKeyPath:(NSString*)keyPath
                          ofObject:(id)object
                            change:(NSDictionary*)change
                           context:(void*)context
    {
        NSUndoManager *undo = [self undoManager];
        // Grab the old value of the key
        id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
        // Add edit item to the undo stack
        [[undo prepareWithInvocationTarget:self] changeKeyPath:keyPath 
                                                      ofObject:object 
                                                       toValue:oldValue];
        // Set the undo action name in the menu
        [undo setActionName:@"Edit"];
    }
    

    can be used to observe changes in properties, creating inverse NSInvocations that will undo edits to those properties.

    Core Data is not needed for undo, but it makes it much, much easier. It handles the creation of these undo actions for you every time you edit your data model, including complex actions like a cascading delete down a hierarchy of managed objects.

    On the iPhone, to enable undo / redo, you need to set up a few things. First, NSManagedObjectContexts on the iPhone don't have an undo manager by default, so you need to create one:

    NSUndoManager *contextUndoManager = [[NSUndoManager alloc] init];
    [contextUndoManager setLevelsOfUndo:10];
    [managedObjectContext setUndoManager:contextUndoManager];
    [contextUndoManager release];       
    

    This code would typically go right after where you would have created your NSManagedObjectContext.

    Once an undo manager is provided for your context, you need to enable the default gesture for undo on the iPhone, a shake of the device. To let your application handle this gesture automatically, place the following code within the -applicationDidFinishLaunching: method in your application delegate:

    application.applicationSupportsShakeToEdit = YES;
    

    Finally, you will need to set up each view controller that will be capable of handling the shake gesture for undo. These view controllers will need to report back the undo manager to use for that controller by overriding the -undoManager method:

    - (NSUndoManager *)undoManager;
    {
        return [[[MyDatabaseController sharedDatabaseController] scratchpadContext] undoManager];
    }
    

    The view controllers will also need to be able to become the first responder to handle gestures, so the following method is needed:

    - (BOOL)canBecomeFirstResponder 
    {
        return YES;
    }
    

    The view controller will need to become the first responder when it appears onscreen. This can be done by calling [self becomeFirstResponder] in -loadView or -viewDidLoad, but I have found that view controllers which appear onscreen immediately after launch need to have this message delayed a bit in order for it to work:

    [self performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.3];
    

    With all this in place, you should get automatic undo and redo support courtesy of Core Data, with a nice animated menu.

    0 讨论(0)
提交回复
热议问题