检测NSUndoManager的警报视图何时可见

时间:2012-01-29 17:24:45

标签: objective-c ios cocoa-touch nstimer nsundomanager

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

我想做什么:我想向我的撤消管理器添加一个有时间限制的调用。如果在时间限制内没有触发撤消,则在设备震动时它将无法使用,因此不会发生任何事情。

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

问题在于,如果我在5秒限制下获得摇动手势,则撤消管理器会显示警报,但如果用户等待直到5s限制后实际点击撤消按钮,没有任何反应:即使警报视图可见,计时器也很乐意清除堆栈。

有没有办法检查并查看警报视图是否可见?如果我能弄清楚用户是否点击撤销或取消,并且如果按下取消按钮则清除撤消管理员的动作堆栈,那将是最好的。

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

谢谢!

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

1 个答案:

答案 0 :(得分:0)

我最终完成了我在编辑中建议的内容 - 使用motionEnded:withEvent手动管理警报和撤消。这样做的缺点是你没有获得内置的撤消警报,它与UIAlertView的风格略有不同,并以摇动的方式进入屏幕。

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

首先,make sure your app can receive shake events并且您可以访问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。我将计时器设置为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;
}

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

希望这有助于某人!