My app starts with a login screen that segues to CreateRequestTableViewController
, and everything is embedded in a navigation controller, so the back button for the CreateRequest
vc goes back to the login screen. I want to ask the user if they're sure they before they're logged out and the navcon pops the vc to show the Login screen again.
I've gotten it to work with the code below, except that after I log back in and move back to the CreateRequest
VC (creating a new instance) I get a fatal error:
'NSInternalInconsistencyException', reason: 'Cannot manually set the delegate on a UINavigationBar managed by a controller.'
This puts me in just a little bit over my head. I've tried adding the deinit
method that's included in the code below, with no luck.
It's especially strange that it doesn't crash the first time I assign the delegate (or when I set it to nil either), as the text of the error would suggest.
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.delegate = self
}
deinit {
navigationController?.navigationBar.delegate = nil
}
func confirmLogout() {
let alert = UIAlertController(title: "Log Out", message: "Are you sure you want to log out?", preferredStyle: .alert)
let yesButton = UIAlertAction(title: "Log out", style: .destructive) { (_) in
if let loginVC = self.navigationController?.viewControllers.first as? SignInTableViewController {
self.navigationController?.popViewController(animated: true)
loginVC.logOutAll()
}
}
let noButton = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(yesButton)
alert.addAction(noButton)
present(alert, animated: true, completion: nil)
}
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
if navigationController?.viewControllers.last is CreateRequestTableViewController {
confirmLogout()
return false
}
navigationController?.popViewController(animated: true)
return true
}
I've solved this problem by deriving custom navigation controller that sets up it's own specialised navigation bar delegate.
This delegate (Forwarder):
The custom navigation controller adds a new "navigationBarDelegate" property that you can use to setup your delegate. You should do that in viewDidAppear:animated: and viewWillDisappear:animated: methods.
Here is the code (Swift 4):
Here is the usage:
Put the following code into your view controller
implement one or more of UINavigationBarDelegate methods in your view controller (this is just an example):
The error message is clear. You are free to set a navigation controller’s delegate. But you must not set the delegate of its navigation bar; you will break the navigation controller if you do that, because it is the delegate of the bar.