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

时间:2010-03-15 17:52:36

标签: iphone ios undo-redo

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

是真的吗?

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

1 个答案:

答案 0 :(得分: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"];
}

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

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

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

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

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

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

application.applicationSupportsShakeToEdit = YES;

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

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

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

- (BOOL)canBecomeFirstResponder 
{
    return YES;
}

视图控制器在屏幕上显示时需要成为第一个响应者。这可以通过调用[self becomeFirstResponder]-loadView中的-viewDidLoad来完成,但我发现启动后立即出现在屏幕上的视图控制器需要将此消息延迟一点才能使其显示工作:

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

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