带有 TapGestureRecognizer 的最前面的 UIView 没有收到触摸

Posted

技术标签:

【中文标题】带有 TapGestureRecognizer 的最前面的 UIView 没有收到触摸【英文标题】:Frontmost UIView with TapGestureRecognizer not receiving touches 【发布时间】:2016-10-20 03:21:33 【问题描述】:

我正在尝试在我的 ios 应用程序的最前面的窗口中添加一个(背景)遮罩视图。在那个掩码视图上,我想添加一个将关闭掩码视图的 UITapGestureRecognizer。最终,我想在中间显示一个弹出窗口(即我的蒙版视图是弹出窗口的褪色背景),但现在我只是无法让我的背景按预期消失。

代码如下所示:我得到最前面的窗口。我创建背景视图并添加 alpha。然后我添加我的手势识别器,将其添加到窗口并添加约束。

但是我的点击手势目标didTapOnMaskView() 永远不会被触发。

private func createMaskView() 

    let applicationKeyWindow = UIApplication.shared.windows.last
    backgroundView = UIView()
    backgroundView.translatesAutoresizingMaskIntoConstraints = false
    backgroundView.backgroundColor = UIColor(white: 0, alpha: 0.2)

    backgroundDismissGesture = UITapGestureRecognizer(target: self, action: #selector(didTapOnMaskView))
    backgroundDismissGesture.numberOfTapsRequired = 1
    backgroundDismissGesture.cancelsTouchesInView = false;
    backgroundView.addGestureRecognizer(backgroundDismissGesture)
    backgroundView.isUserInteractionEnabled = true

    backgroundView.alpha = 0.0

    UIView.animate(withDuration: 0.4)  
        self.backgroundView.alpha = 1.0
    

    applicationKeyWindow.addSubview(backgroundView)

    let views: [String: UIView] = [ "backgroundView": backgroundView]

    var allConstraints = [NSLayoutConstraint]()

    let verticalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|-0-[backgroundView]-0-|", options: [], metrics: nil, views: views)
    allConstraints += verticalConstraint

    let horizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|-0-[backgroundView]-0-|", options: [], metrics: nil, views: views)
    allConstraints += horizontalConstraint

    NSLayoutConstraint.activate(allConstraints)

    // This is super odd, but the gesture gets triggered until the following code block executes
    DispatchQueue.main.asyncAfter(deadline: .now() + 3.1) 
        applicationKeyWindow.bringSubview(toFront: self.backgroundView)
    



func didTapOnMaskView() 
    hide()


func show()
    createMaskView()

** 编辑 ** 在运行了更多诊断之后,我注意到如果我在 createMaskView() 的末尾添加一个延迟三秒的代码块,将 maskView 带到前面,则手势在前 3.1 秒内有效,直到该块的代码被执行。请注意,如果该代码块不存在,则手势识别器根本不起作用(甚至 3.1 秒)。

【问题讨论】:

【参考方案1】:

由于您希望背景视图与其父视图具有相同的大小,您可以尝试设置帧大小而不是使用约束。

let backgroundView = UIView(frame: applicationKeyWindow.frame)

过去在类似情况下对我有用。

我希望这会有所帮助!祝你有美好的一天!

【讨论】:

不幸的是,我仍然无法收到触摸。似乎没有任何改变... 我知道这看起来很奇怪,但您可以尝试在应用手势识别器之前激活约束。 我使用了 UIScreen 窗口边界UIView(frame: UIScreen.main.bounds) 还是没有运气。不过谢谢!【参考方案2】:

事实证明,不维护对包含我的 maskView 的视图的引用是问题所在。在创建此视图的 ViewController 中,我将 showPopUp() 函数更改如下:

// Stored property on my View Controller class
var myPopupView: UIView?

private func showLMBFormSubmittedPopup()
    let popupView = MyPopupView()
    popupView.show()

    // Once I added this line, it started working
    myPopupView = popupView

也许有人可以解释为什么会发生这种情况。我怀疑 ARC 正在释放我的 UITapGestureRecognizer 占用的内存,因为我的代码不再引用它。

【讨论】:

以上是关于带有 TapGestureRecognizer 的最前面的 UIView 没有收到触摸的主要内容,如果未能解决你的问题,请参考以下文章

如何为多个 UILabel 创建一个 tapGestureRecognizer?

iOS:TapGestureRecognizer 问题

将 TapGestureRecognizer 添加到除 UICollectionView 单元格之外的整个视图

Xcode 中的 Swift Playground - 到 UILabel 的 TapGestureRecognizer 不起作用

iOS - TapGestureRecognizer - 点击适用于整个屏幕而不是视图

将tapGestureRecognizer添加到其背景视图时无法触发collectionview的事件