Dismiss UIView within ViewController by tapping outside of UIView

2.6k Views Asked by At

I'm presenting a UIView over my ViewController which contains a table view that covers the whole view controller. I want to dismiss the UIView when tapping outside of the UIView, but have not found anything that helps the cause. This is what I'm trying to do, and it should work but it's not registering touches even if the UIView is not presented. Anyone dealt with a similar issue?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch: UITouch? = touches.first

        if touch?.view != fullSessionView {
            fullSessionView?.removeFromSuperview()
        }
    }
3

There are 3 best solutions below

3
aheze On

You should always call super, like this:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event) /// always call the super

But anyway, you want to see if fullSessionView contains the touch. So instead of checking the view where the touch happened, you probably want to check the location of where the touch happened. Something like this:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    let touch = touches.first
    guard let location = touch?.location(in: fullSessionView) else { return }
    if !fullSessionView.frame.contains(location) {

         /// tapped outside fullSessionView
         fullSessionView?.removeFromSuperview()
    }
}
0
pietrorea On

First, I'd try to see if any of the built-in presentation styles could work for you. But you'd have to embed your view in a view controller.

If you want to stick with a UIView you could try presenting your UIView on top of a transparent background UIView that covers the whole screen and attaching a UIGestureRecognizer to the transparent background.

Tapping the background would trigger a call back (via delegate, closure, etc) that would then remove your view.

0
Apps Maven On

You need to initialize UITapGestureRecognizer with a target and action to your view to be added, like so:

let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTap(_:)))
myView.addGestureRecognizer(tap)
Then, you should implement the handler, which will be called each time when a tap event occurs:
@objc func handleTap(_ sender: UITapGestureRecognizer? = nil) {
    self.removefromSuperview() // this will remove added view from parent view
}