UIWindow子类中的Shake Gesture检测接管默认文本undo manager

时间:2010-08-13 12:02:21

标签: iphone uiwindow nsundomanager

我想要的是让我的iPhone应用程序始终知道摇动手势,除非任何UITextfieldUITextview成为firstResponder。

(我跟着这个:https://stackoverflow.com/questions/150446/how-do-i-detect-when-someone-shakes-an-iphone/1351486#1351486I

我将UIWindow子类化并实现了motionEnded:withEvent:方法,即使我将UITextView设置为firstResponder也能正常工作。我的自定义UIWindow会调用motionEnded:withEvent:,即使它不是第一个响应者。

问题是我UItextView的默认撤消管理器不再响应。无论视图层次结构或firstResponder如何更改,UIWindow都会接管Shake-Gesture的所有处理。

有没有人能够了解如何暂时禁用UIWindow的检测或让当前的firstResponder根据我的实现接管Shaking-Gesture?

提前致谢!

1 个答案:

答案 0 :(得分:1)

无论如何我找到了解决方案。

默认的撤消管理器实际上仍然保存了对UITextView进行的所有操作。

由于UIWindow接管了动作处理,首先我尝试通过覆盖包含motionEnded:withEvent:的viewController中的UITextView来取回它。

其次,通过[myTextView undoManager]获取undoManager,然后您可以向其发送undoredo条消息。

现在模仿默认的撤消管理员提醒视图,使用redoMenuItemTitleundoMenuItemTitle获取按钮标题,然后使用canUndocanRedo来决定是否显示按钮

修改:以下是我的应用程序中的代码:

- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event {
    if (event.type == UIEventTypeMotion && event.subtype == UIEventSubtypeMotionShake) {

        //textUndoManager is an ivar but it was just a reference to the undoManager
        //textUndoManager = [myTextView undoManager]; <--- in viewDidLoad:
        NSString *undoButtonTitle = nil;
        NSString *redodoButtonTitle = nil;
        NSString *alertViewTitle = nil;
        if ([textUndoManager canUndo])
            undoButtonTitle = [NSString stringWithString:[textUndoManager undoMenuItemTitle]];
        if ([textUndoManager canRedo])
            redodoButtonTitle = [NSString stringWithString:[textUndoManager redoMenuItemTitle]];
        if (!undoButtonTitle && !redodoButtonTitle)
            alertViewTitle = @"Nothing to Undo";

        UIAlertView *alertView;
        if (undoButtonTitle == nil) {
            alertView = [[UIAlertView alloc] initWithTitle:alertViewTitle message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:redodoButtonTitle, nil];
        } else {
            alertView = [[UIAlertView alloc] initWithTitle:alertViewTitle message:nil delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:undoButtonTitle, redodoButtonTitle, nil];
        }

        [alertView show];
    }
}

//UIAlertViewDelegate
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
    if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:[textUndoManager undoMenuItemTitle]]) {
        [textUndoManager undo];
    }
    if ([[alertView buttonTitleAtIndex:buttonIndex] isEqualToString:[textUndoManager redoMenuItemTitle]]) {
        [textUndoManager redo];
    }
}