undo/redo如何在iPhone OS上运行?

don*_*ile 12 iphone undo-redo ios

我的应用尚未使用Core Data.我必须使用Core Data进行撤销/重做吗?

而且:用户如何进行撤销/重做?我从来没有见过它,从来没有使用它.如果我愿意,不知道我应该怎么做.任何地方都没有撤消/重做按钮.然而他们说它有撤消/重做.那么用户如何触发这个呢?

Bra*_*son 35

iPhone OS 3.0从Mac中引入了NSUndoManager的概念,这就是在iPhone上实现撤销的功能.NSUndoManager维护一组NSInvocations,这些操作与您所做的任何编辑或其他更改相反.例如,

- (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"];
}
Run Code Online (Sandbox Code Playgroud)

可以用来观察属性的变化,创建反向NSInvocations,撤消对这些属性的编辑.

撤消不需要核心数据,但它更容易实现.每次编辑数据模型时,它都会为您处理这些撤消操作的创建,包括复杂的操作,如级联删除托管对象的层次结构.

在iPhone上,要启用撤消/重做,您需要设置一些内容.首先,iPhone上的NSManagedObjectContexts默认没有撤消管理器,因此您需要创建一个:

NSUndoManager *contextUndoManager = [[NSUndoManager alloc] init];
[contextUndoManager setLevelsOfUndo:10];
[managedObjectContext setUndoManager:contextUndoManager];
[contextUndoManager release];       
Run Code Online (Sandbox Code Playgroud)

此代码通常会在您创建NSManagedObjectContext之后立即执行.

为您的上下文提供撤消管理器后,您需要在iPhone上启用撤消的默认手势,即摇动设备.要让您的应用程序自动处理此手势,请将以下代码放在-applicationDidFinishLaunching:应用程序委托中的方法中:

application.applicationSupportsShakeToEdit = YES;
Run Code Online (Sandbox Code Playgroud)

最后,您需要设置每个视图控制器,以便能够处理用于撤消的摇动手势.这些视图控制器需要通过覆盖-undoManager方法来报告用于该控制器的撤消管理器:

- (NSUndoManager *)undoManager;
{
    return [[[MyDatabaseController sharedDatabaseController] scratchpadContext] undoManager];
}
Run Code Online (Sandbox Code Playgroud)

视图控制器还需要能够成为第一个处理手势的响应者,因此需要以下方法:

- (BOOL)canBecomeFirstResponder 
{
    return YES;
}
Run Code Online (Sandbox Code Playgroud)

当视图控制器出现在屏幕上时,它将需要成为第一个响应者.这可以通过调用来完成[self becomeFirstResponder]-loadView还是-viewDidLoad,但我发现,出现在发射后立即在屏幕上的视图控制器需要有这样的消息延迟在整理了一下它的工作:

[self performSelector:@selector(becomeFirstResponder) withObject:nil afterDelay:0.3];
Run Code Online (Sandbox Code Playgroud)

有了这一切,您应该获得Core Data的自动撤消和重做支持,并提供一个很好的动画菜单.