【问题标题】:detecting when NSUndoManager's alert view is visible检测 NSUndoManager 的警报视图何时可见
【发布时间】:2012-01-29 17:24:44
【问题描述】:

我将描述我正在尝试做的一般情况(以防有更好的方法),然后是我遇到的绊脚石(以防我的方法是最好的方法)。

我想做的事:我想向我的撤消管理器添加一个有时间限制的调用。如果在时限内没有触发undo,那么摇动设备时就无法使用undo,因此什么也不会发生。

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

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

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

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

谢谢!

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

【问题讨论】:

  • 我认为使用motionEnded:withEvent 方法是可行的方法。 UIAlertView 基本上是一个 UIWindow,也许您可​​以检查您的主应用程序的窗口何时再次变为键,以便您知道撤消警报视图已被解除。
  • 嗯,好点子。我想我会选择motionEnded的东西。如果它有效,我会在这里回复。谢谢!

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


【解决方案1】:

我最终按照我在编辑中的建议进行了操作 - 使用 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;
}

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

希望这对某人有所帮助!

【讨论】:

    猜你喜欢
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多