简体   繁体   中英

Removing UIView via UITapGestureRecognizer requires 2 clicks (swift)

I have created a view that overlays the entire screen when a button is selected. Specifically, I have a UIButton inside my UICollectionViewCell and when clicked, it renders the overlay over the device's entire window. The overlay is a UIView hierarchy, with UIVisualEffectView being the parent view of the overlay. UIVisualEffectView is added as a subview to the ViewController.view property when the aforementioned UIButton is selected.

I also added a UITapGestureRecognizer to the UIVisualEffectView. When selected, the entire overlay should go away, via removal from the ViewController.view subviews.

The only issue is the behavior of the UITapGestureRecognizer. I must click it twice for the overlay to go away. Adding trace print statements show that on the first click, the UITapGestureRecognizer action #selector function is firing, but it isn't until I either click it again, or click the simulators frame (ie. to move the simulator), that the overlay disappears properly. I suspect this could have to do with threads and returning control, but can't pinpoint it. Below is the relevant code. Any help is appreciated.

Note: I have run this with and without the removeFromSuperview statement being in the DispatchQueue.main.async() block; the behavior is the same with and without.

Setup in UIViewController subclass:

var blurBackground = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.dark))

blurBackground.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(unblurView)))    

Target action, confirmed to be firing via trace statements:

func unblurView() {
    UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
        print("In unblur func")
        self.blurBackground.alpha = 0.0

        DispatchQueue.main.async(execute: {
            self.blurBackground.removeFromSuperview()
            print("In unblur func - main thread removefromsuperview")
        })

    }, completion: nil)
}

If it is helpful, I can add the code relating to adding the overlay view to the view controller view's subviews.

Creating a new Single View App project with the following view controller works just fine for me

class ViewController: UIViewController {

    var blurBackground = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.dark))

    override func viewDidLoad() {
        super.viewDidLoad()
        blurBackground.frame = self.view.frame
        blurBackground.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(ViewController.unblurView)))
        view.addSubview(blurBackground)
    }

    @objc func unblurView() {
        UIView.animate(withDuration: 0.2, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            print("In unblur func")
            self.blurBackground.alpha = 0.0
            DispatchQueue.main.async(execute: {
                self.blurBackground.removeFromSuperview()
                print("In unblur func - main thread removefromsuperview")
            })
        }, completion: nil)
    }
}

how are you adding the blurBackground to the view?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM