iOS 8.x 中的 UIAlertController 无法响应触摸事件,触摸事件是不是发送到键窗口对象?

Posted

技术标签:

【中文标题】iOS 8.x 中的 UIAlertController 无法响应触摸事件,触摸事件是不是发送到键窗口对象?【英文标题】:UIAlertController in iOS 8.x cannot response touch event, is the touch event sent to the key window object?iOS 8.x 中的 UIAlertController 无法响应触摸事件,触摸事件是否发送到键窗口对象? 【发布时间】:2015-04-07 03:29:39 【问题描述】:

我有一个关于 UIAlertController 的问题。它不能接收任何触摸事件并被解雇。 我以这种方式发送警报:

UIViewController *controller =[UIApplication sharedApplication].keyWindow.rootViewController
[controller presentViewController:alertController animated:YES completion:nil];

在这个时间之后,出现了警报视图。但是当我尝试单击“确定”时,没有任何响应。于是我点击了alert view周围的空白区域,下层的按钮接收并做出响应。

在我的应用程序中,有一个第三方 SDK,它提供了一个暂停按钮和登录/注销 UI。该按钮将始终存在,但除非我调用它,否则不会显示 UI。 SDK 在初始化时会将两个窗口添加到应用程序的窗口数组中。 所以“[UIApplication sharedApplication].windows”中有三个对象。 看起来像这样:

[0]:”<TS_PlatformWindow: 0x16e15ac0; baseClass = UIWindow; frame = (0 0; 568 320); gestureRecognizers = <NSArray: 0x186a85b0>; layer = <UIWindowLayer: 0x186a8a20>>",
[1]:”<UIWindow: 0x16e1a060; frame = (0 0; 568 320); autoresize = W+H; tag = 10000000; gestureRecognizers = <NSArray: 0x16e19af0>; layer = <UIWindowLayer: 0x16e19f40>>",
[2]:“<UITextEffectsWindow: 0x16f576c0; frame = (0 0; 568 320); opaque = NO; gestureRecognizers = <NSArray: 0x16f57120>; layer = <UIWindowLayer: 0x16f574b0>>"

索引 1 处的应用程序窗口,索引 0 和 2 处的窗口是第三方 SDK。

作为 ios 开发者库中的官方文档,引用如下: “一个事件沿着特定的路径传播,直到它被传递给一个可以处理它的对象。首先,单例 UIApplication 对象从队列顶部获取一个事件并调度它进行处理。 通常,它将事件发送到应用程序的关键窗口对象,该对象将事件传递给初始对象进行处理。初始对象取决于事件的类型。 来自https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/event_delivery_responder_chain/event_delivery_responder_chain.html

据我了解,触摸事件应该发送到应用程序的关键窗口,但实际上我的应用程序的窗口不是。 该文档使用“典型”一词,因此我不确定我的应用程序中的情况是否是一个例外。如果存在多个窗口,则没有提及事件如何传递。

所以我像这样更改我的代码:

UIViewController *controller =[UIApplication sharedApplication].keyWindow.rootViewController
for (UIWindow *win in wins.reverseObjectEnumerator) 
      UIViewController *rootController = win.rootViewController;
      if (rootController != nil) 
           controller = rootController;
           break;
     

[controller presentViewController:alertController animated:YES completion:nil];

“controller”的默认值将被分配给“keyWindow.rootViewController” 以相反的顺序移动应用程序的窗口数组,并选择最顶层对象的“rootViewController”来显示警报。 有效!

如果这是正确的解决方案,这个问题让我感到困惑?或者有其他文件可以解释吗?

PS:

每个操作都在主线程上

【问题讨论】:

【参考方案1】:

我无法从 UIAlertController 访问背景视图,因此对当前 keyWindow 使用 addGestureRecognizer -

class MyAlertController: UIAlertController, UIGestureRecognizerDelegate 

var tapGesture : UITapGestureRecognizer?

override func viewDidAppear(animated: Bool)

    tapGesture = UITapGestureRecognizer(target: self, action:Selector("tapGesture:"))
    tapGesture!.delegate = self
    UIApplication.sharedApplication().keyWindow?.addGestureRecognizer(tapGesture!)


func tapGesture(sender: UITapGestureRecognizer? = nil)

    UIApplication.sharedApplication().keyWindow?.removeGestureRecognizer(tapGesture!)
    self.dismissViewControllerAnimated(true, completion: nil)


【讨论】:

以上是关于iOS 8.x 中的 UIAlertController 无法响应触摸事件,触摸事件是不是发送到键窗口对象?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 iOS7 中的 UIAlertController 收到 nil 值?

iOS 8.x 中的 UIAlertController 无法响应触摸事件,触摸事件是不是发送到键窗口对象?

UIAlertController 在 iOS 9 中不起作用

iOS 版本更新摘要iOS 8.x

仅为 OS X 10.8.x 和 iOS 6.x 在 iCloud 中启用核心数据同步

iOS 11坑惨iPhone6/6S/7/8/X!苹果神回应