James Jarrett James Jarrett -3 years ago 147
iOS Question

SubView(nib) wont remove after calling removeFromSuperView()

I have an overlay view to segregate content, I'm checking for authentication in viewWillAppear() and I have a Notification subscribed to my Auth method. If I authenticate before any of my other views appear the overlay does not show up, however it does on the first view and will not go away even after calling removeFromSuperView().

import UIKit
import FirebaseAuth

class ProtectedViewController: UIViewController, ForceSignInBannerDelegate,
SignUpViewControllerDelegate, LoginViewControllerDelegate{


override func viewDidLoad() {
super.viewDidLoad()
}

override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(true)
NotificationCenter.default.addObserver(self, selector: #selector(checkAuthentication), name: .myNotification, object: nil)
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
self.checkAuthentication()

}

func checkAuthentication() {
let bannerViewController = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
bannerViewController.delegate = self

if (!AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: false)
print("Need to login")
} else if(AuthenticationService.sharedInstance.isAuthenticated()) {
self.setView(view: bannerViewController, hidden: true)
}
}

func setView(view: UIView, hidden: Bool) {
UIView.transition(with: view, duration: 0.5, options: .transitionCrossDissolve, animations: { _ in

view.isHidden = hidden
if hidden {
view.removeFromSuperview()
} else {
self.view.addSubview(view)
}

}, completion: nil)
}

Answer Source

It's because you're trying to remove a new ForceSignInBanner each time. Ideally you should create it once and keep a reference to the ForceSignInBanner created (as an optional property of ProtectedViewController).

Then remove the ForceSignInBanner that you've stored in the property.

    class ProtectedViewController: UIViewController, ForceSignInBannerDelegate {

        // This lazily loads the view when the property is first used and sets the delegate.
        // Ideally you wouldn't force-case the `as` but I've left it for simplicity here.

        private lazy var forceSignInBannerView: ForceSignInBanner = {
            let forceSignInBannerView  = ForceSignInBanner.instanceFromNib() as! ForceSignInBanner
            forceSignInBannerView.delegate = self
            return forceSignInBannerView
        }()

        // ... your other code ... //

        fun toggleForceSignInBannerViewVisibility(isVisible: Bool) {
            if isVisible {
                view.addSubview(forceSignInBannerView)
            } else {
                forceSignInBannerView.removeFromSuperview()
            }
        }

    }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download