How does undo/redo basically work on iPhone OS?

做~自己de王妃 提交于 2019-12-17 10:31:43

问题


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 action, and never ever used it. Don't know how I should do it if I wanted to. There's no undo/redo button anywhere. Yet they say it has undo/redo. So how does the user trigger this?


回答1:


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.



来源:https://stackoverflow.com/questions/2449268/how-does-undo-redo-basically-work-on-iphone-os

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!