I'm trying to add a (background) mask view to the front most window in my iOS app. On that mask view I want to add a UITapGestureRecognizer that will dismiss the mask view. Ultimately, I want to display a popup in the middle (i.e. my mask view is a faded background for the popup), but for now I'm just having trouble getting my background to dismiss as expected.
The code looks like this: I get the front most window. I create the background view and add alpha. Then I add my gesture recognizer, add it to the window and add constraints.
However my tap gesture target didTapOnMaskView()
never gets triggered.
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()
}
** EDIT **
After running some more diagnostics, I've noticed that if I add a three-second-delayed block of code to the end of my createMaskView()
that brings the maskView to the front, the gesture works for the first 3.1 seconds until that block of code is executed. Note that if that code block is not there, the gesture recognizer doesn't work at all (not even 3.1 seconds).