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 中不起作用