点击 UIKeyboard 时触发 hitTest

发布于 2024-12-14 11:19:09 字数 542 浏览 2 评论 0原文

我正在尝试修复一个涉及 UIView hitTest:withEvent: 的错误,当触摸在 UIKeyboard 上时,但仅在应用程序进入后台后,才会在我的视图上调用。

它发生在我的具有复杂视图层次结构的应用程序中,因此我在只有 2 个视图的应用程序中重现了它:

  • 1 UIView 768x1024(全屏)
  • ​​1 UITextView 200x200 在全屏视图的上半部分

行为如下:

  • 点击 textview 会导致全屏视图的 hitTest 方法触发,文本字段成为第一响应者,然后键盘按预期显示。敲击键盘按键效果很好。
  • 现在关闭键盘。
  • 将应用程序发送到后台。
  • 然后恢复应用程序。
  • 再次使文本视图成为第一响应者。麻烦来了,现在当点击键盘上的按键时,全屏视图的 hitTest 方法将被触发。

我在 iOS 5 iPad 2 上看到了这一点。不过,仅在设备上,从未在模拟器中看到过。知道为什么 hitTesting 会以这种方式搞砸吗?谢谢。

I'm trying to fix a bug that involves UIView hitTest:withEvent: being called on my view when the touches are on the UIKeyboard, but only after the app has been in the background.

It was occurring in my app with a complex view hierarchy so I reproduced it in an app with only 2 views:

  • 1 UIView 768x1024 (fullscreen)
  • 1 UITextView 200x200 in the upper half of the fullscreen view

The behavior is as follows:

  • Tapping the textview causes the fullscreen view's hitTest method to fire, the textfield becomes first responder, and then the keyboard appears all as expected. Tapping on keyboard keys works fine.
  • Now dismiss the keyboard.
  • Send the app to the background.
  • Then resume the app.
  • Make the textview first responder again. Here's the trouble, now when tapping keys on the keyboard the fullscreen view's hitTest method is firing.

I'm seeing this on an iOS 5 iPad 2. Only on device though, never in the simulator. Any idea why hitTesting could get messed up in this way? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

肤浅与狂妄 2024-12-21 11:19:09

上述问题似乎是由键盘的 UIWindow 卡在错误状态引起的。确保键盘窗口的隐藏属性设置为“是”(即使它已经是“是”)可以解决我的问题。这可以在 UIApplicationDelegate 类中完成:

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // The keyboard sometimes disables interaction when the app enters the 
    // background due to an iOS bug. This brings it back to normal.
    for (UIWindow *testWindow in [UIApplication sharedApplication].windows) {
        if (!testWindow.opaque && [NSStringFromClass(testWindow.class) hasPrefix:@"UIText"]) {
            BOOL wasHidden = testWindow.hidden;
            testWindow.hidden = YES;

            if (!wasHidden) {
                testWindow.hidden = NO;
            }

            break;
        }
    }
}

键盘窗口的类名称(至少在具有标准美国键盘的 iOS 5 中)是 UITextEffectsWindow。像往常一样,依赖未记录的类名不是一个好主意,但在特定于操作系统的错误的情况下,它可以满足我的目的。可能有任意数量的窗口,包括根应用程序窗口、键盘、警报以及您的应用程序或其他框架添加的其他窗口,因此不要太具体。

The issue described above seems to be caused by the keyboard's UIWindow getting stuck in a bad state. Ensuring that the keyboard window's hidden property gets set to YES (even if it is already YES) fixes the problem for me. This can be done in your UIApplicationDelegate class:

- (void)applicationWillEnterForeground:(UIApplication *)application {
    // The keyboard sometimes disables interaction when the app enters the 
    // background due to an iOS bug. This brings it back to normal.
    for (UIWindow *testWindow in [UIApplication sharedApplication].windows) {
        if (!testWindow.opaque && [NSStringFromClass(testWindow.class) hasPrefix:@"UIText"]) {
            BOOL wasHidden = testWindow.hidden;
            testWindow.hidden = YES;

            if (!wasHidden) {
                testWindow.hidden = NO;
            }

            break;
        }
    }
}

The class name of the keyboard window, at least in iOS 5 with a standard US keyboard, is UITextEffectsWindow. As usual it is not a good idea to rely on undocumented class names but in the case of an OS-specific bug it works for my purposes. There could be any number of windows, including the root application window, keyboard, alerts, and other windows that your app or other frameworks have added, so don't be too inspecific.

ヤ经典坏疍 2024-12-21 11:19:09

这里有同样的问题。仅当我回家并返回应用程序时才会发生这种情况。
在第一次新运行中不会发生。

这也与iOS5有关。

Got the same issue here. It does happen ONLY when I hit home and return to the app.
Does not happen in the first fresh run.

And it is related to iOS5 as well.

萌辣 2024-12-21 11:19:09

我遇到了同样的问题,我的解决方法是监听 UIKeyboardDidShowNotification 和 UIKeyboardDidHideNotification,使用 UIKeyboardFrameEndUserInfoKey 计算键盘高度,然后在我的 hitTest:withEvent: 方法中我会看到点击是否在键盘“区域”上。

I got the same problem, and my work around is to listen to UIKeyboardDidShowNotification and UIKeyboardDidHideNotification, calculate the keyboard height using UIKeyboardFrameEndUserInfoKey, then in my hitTest:withEvent: method I would see whether the hit was on the keyboard "zone" or not.

似梦非梦 2024-12-21 11:19:09

只是为了扩展@enzo-tran的答案,这就是我最终所做的:我向我的 UIView 子类添加了一个keyboardRect属性,注册了 UIKeyboardDidShowNotificationUIKeyboardDidHideNotification,并补充道:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  if (CGRectContainsPoint([self keyboardRect], point)) {
    // Ignore      
  } else {
    ...
  }
}

- (void)keyboardDidShow:(NSNotification *)notif {
    CGRect keyboardRect;

    [[[notif userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
    keyboardRect = [self convertRect:keyboardRect fromView:nil];

    [self setKeyboardRect:keyboardRect];
}

- (void)keyboardDidHide:(NSNotification *)notif {
    [self setKeyboardRect:CGRectZero];
}

Just to expand on the answer by @enzo-tran , this is what I ended up doing: I added a keyboardRect property to my UIView subclass, registered for UIKeyboardDidShowNotification and UIKeyboardDidHideNotification, and added:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
  if (CGRectContainsPoint([self keyboardRect], point)) {
    // Ignore      
  } else {
    ...
  }
}

- (void)keyboardDidShow:(NSNotification *)notif {
    CGRect keyboardRect;

    [[[notif userInfo] valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardRect];
    keyboardRect = [self convertRect:keyboardRect fromView:nil];

    [self setKeyboardRect:keyboardRect];
}

- (void)keyboardDidHide:(NSNotification *)notif {
    [self setKeyboardRect:CGRectZero];
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文