2

我将描述我一般要做什么(以防有更好的方法),然后是我遇到的绊脚石(以防我的方法是最好的方法)。

我想要做什么:我想向我的撤消管理器添加一个有时间限制的调用。如果在时限内没有触发撤销,那么在摇晃设备时撤销将无效,因此不会发生任何事情。

我在做什么:我的方法是使用 anNSUndoManagerNSTimer. 当我将调用添加到撤消管理器时,我也启动了一个 5 秒计时器。当计时器触发时,它会检查!self.undoManager.isUndoing是否为真,然后继续并从撤消管理器中删除所有操作。在模拟器中对其进行测试是有效的:摇动手势会在 5 秒之前启动撤消,但不会在之后。

问题是,如果我在 5 秒限制下得到一个摇动手势,撤消管理器会显示警报,但是如果用户等到 5 秒限制之后才真正点击撤消按钮,则什么也没有发生:计时器很高兴地清除了堆栈,即使警报视图可见。

有没有办法检查警报视图是否可见?最好是如果我能弄清楚用户是否也点击了撤消或取消,并在按下取消按钮时清除撤消管理器的操作堆栈。

或者除了以这种方式使用计时器之外还有更好的方法吗?

谢谢!

编辑添加:我的另一个想法是自己(通过motionEnded:withEvent:调用)捕获抖动事件并手动管理警报和撤消堆栈。与上述相比,对此的想法也值得欢迎。

4

1 回答 1

0

我最终按照我在编辑中的建议进行了操作——用于motionEnded:withEvent手动管理警报和撤消。这样做的缺点是你没有得到内置的撤消警报,它的风格与 a 略有不同,UIAlertView并以摇晃的动作进入屏幕。

好处是我现在有一个 10 秒后过期的撤消。以下是代码的一般结构,以防您想要相同的内容。

首先,确保您的应用可以接收震动事件并且您有一个NSUndoManager可以访问的。您还需要一个计时器;我的代码设置为NSTimer在发生可撤消事件并持续 10 秒时启动。确保在计时器启动的同一计时器上添加撤消目标,以便实际上有一些东西可以撤消。

接下来,motionEnded:withEvent像这样实现:

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (motion == UIEventSubtypeMotionShake && [self.undoManager canUndo]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Undo something?" message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Undo", nil];
        [alert show];
        undoAlertIsVisible_= YES;
    }
}

我正在使用undoAlertIsVisible_此处调用的 ivar 来跟踪我的警报是否在屏幕上。

在计时器的回调中,执行以下操作:

if (!self.undoManager.isUndoing && !undoAlertIsVisible_) {
    // Clear away the possible undo
    [self.undoManager removeAllActionsWithTarget:self];
}
undoTimer_ = nil;

在这里,我们检查一下我们当前没有撤消,并且警报不可见。如果是这样,请删除撤消操作并将计时器(另一个 ivar)设置为零。我将计时器设置为 nil,以便我可以检查它是否在我的警报回调中被触发,这里是:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if (buttonIndex != alertView.cancelButtonIndex) {
        if (self.undoManager.canUndo) {
            [self.undoManager undo];
        }
    }
    else {
        if (!undoTimer_) {
            // Timer fired while we were staring at the alert
            [self.undoManager removeAllActionsWithTarget:self];
        }
    }
    undoAlertIsVisible_= NO;
}

在警报回调中,我们要么使撤消发生,要么,如果在警报可见并且警报被取消时触发计时器,我们清除可能的撤消操作。否则,撤消操作将在取消后挂起,没有计时器来清除它。

希望这对某人有帮助!

于 2012-02-10T21:52:52.457 回答