iosswiftuiblureffect

Swift blur effect is not dismissed when returning to main view


I want to show a subview, which is transperrent, therefore blur the main view controller. This works fine, but when returning to the main view controller, the blur stays - and it doesn't go to any section in the main view, like view did appear or popoverPresentationControllerDidDismissPopover.

I run this code to create the blur and show the subview:

if !UIAccessibilityIsReduceTransparencyEnabled() {
    self.view.backgroundColor = UIColor.clear

    let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.extraLight)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = self.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]

    self.view.addSubview(blurEffectView)
}

let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PriceAlarmPopUp") as!  PriceAlarmPopupViewController
self.addChildViewController(popOverVC)
popOverVC.view.frame = self.view.frame
self.view.addSubview(popOverVC.view)

popOverVC.didMove(toParentViewController: self)

When finishing the subview, I do:

self.view.removeFromSuperview()

Is there anything I do wrong? I tried already several solutions, but was not able to get rid of the blur subview.


Solution

  • Keep weak reference for your blur view, and later remove it from superview:

    class MyVC: UIViewController {
    
        private weak var blurView: UIView?
    
        func foo() {
            if !UIAccessibilityIsReduceTransparencyEnabled() {
                self.view.backgroundColor = UIColor.clear
                let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.extraLight)
                let blurEffectView = UIVisualEffectView(effect: blurEffect)
                blurEffectView.frame = self.view.bounds
                blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
                self.view.addSubview(blurEffectView)
                blurView = blurEffectView // HERE YOU SAVE WEAK REFERENCE
            }
    
            let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PriceAlarmPopUp") as!  PriceAlarmPopupViewController
            self.addChildViewController(popOverVC)
            popOverVC.view.frame = self.view.frame
            self.view.addSubview(popOverVC.view)
    
            popOverVC.didMove(toParentViewController: self)
        }
    
        func fooDone() {
            blurView?.removeFromSuperview() // Blur view will be removed from sureview and automatically `blurView` becomes to `nil`
        }
    }
    

    If you want to hide it from another view controller, use closures:

    class MyVC: UIViewController {
        func foo() {
            let popOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "PriceAlarmPopUp") as!  PriceAlarmPopupViewController
            self.addChildViewController(popOverVC)
            popOverVC.view.frame = self.view.frame
            if !UIAccessibilityIsReduceTransparencyEnabled() {
                self.view.backgroundColor = UIColor.clear
                let blurEffect = UIBlurEffect(style: UIBlurEffectStyle.extraLight)
                let blurEffectView = UIVisualEffectView(effect: blurEffect)
                blurEffectView.frame = self.view.bounds
                blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
                self.view.addSubview(blurEffectView)
                popOverVC.userTappedCloseButtonClosure = { [weak blurEffectView] in
                    blurEffectView?.removeFromSuperview()
                }
            }
            self.view.addSubview(popOverVC.view)
            popOverVC.didMove(toParentViewController: self)
        }
    }
    
    class PriceAlarmPopupViewController: UIViewController {
        public var userTappedCloseButtonClosure: (() -> Void)?
    
        @IBAction func closeButtonAction(_ sender: Any) {
            userTappedCloseButtonClosure?()
        }
    }