I want to show an alert with Confirmation when user clicks on back button. This is how I\'m trying to add action.
self.navigationItem.hidesBackButton = true
You need add custom back button to Navigation bar, and add action to it
let backButton = UIBarButtonItem (image: UIImage(named: "ico-nav-prev")!, style: .plain, target: self, action: #selector(GoToBack))
self.navigationItem.leftBarButtonItem = backButton
self.navigationItem.hidesBackButton = true
func GoToBack(){
self.navigationController!.popViewController(animated: true)
}
I don't know what you try to achive, but isn't it a possible solution to do, what you want, whenever vieWillDisappear:
got called? This is maybe a matching entrypoint without fiddeling around with the back-bar-button suggested in the other answers.
Better
Another option would be to implement the UINavigationControllerDelegate
, set your controller as delegate
and then implement your alert in navigationController(_:willShow:animated:)
.
Take a look here for reference.
I found a solution!
I tested it on iOS 11 and iOS 13 and it works fine :)
protocol CustomNavigationViewControllerDelegate {
func shouldPop() -> Bool
}
class CustomNavigationViewController: UINavigationController, UINavigationBarDelegate {
var backDelegate: CustomNavigationViewControllerDelegate?
func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
return backDelegate?.shouldPop() ?? true
}
}
class SecondViewController: UIViewController, CustomNavigationViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
(self.navigationController as? CustomNavigationViewController)?.backDelegate = self
}
func shouldPop() -> Bool {
if (needToShowAlert) {
showExitAlert()
return false
} else {
return true
}
}
}
This might help. This wont override back action, but you can do additional task.
Objective c
-(void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
if(self.isMovingFromParentViewController)
{
//On click of back or swipe back
}
if(self.isBeingDismissed)
{
//Dismissed
}
NSLog(@"%d",self.isBeingDismissed);
NSLog(@"%d",self.isMovingFromParentViewController);
}
Swift
override func viewWillDisappear(_ animated: Bool)
{
super.viewWillDisappear(animated);
if self.isMovingFromParentViewController
{
//On click of back or swipe back
}
if self.isBeingDismissed
{
//Dismissed
}
}
I think this answer should do the job.
You basically create your button with the default style and register a selector.
And you might try this for a backButton instead of leftButton:
Objective-C
UIBarButtonItem *backBtn = [[UIBarButtonItem alloc] init];
[desVC.navigationItem setBackBarButtonItem:backBtn];
Swift
let backBtn = UIBarButtonItem()
self.navigationItem.backBarButtonItem = backBtn
Call this line of code inside of your ParentViewController
's viewDidLoad
method not the ChildViewController
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
Remove the following line of code from your ChildViewController
self.navigationItem.hidesBackButton = true
And you'll be Ok! If you need to create an action for this transition, I mean whenever the user taps the back button from your ChildViewController
. Simply call this method inside of your ChildViewController
override func didMove(toParentViewController parent: UIViewController?) {
super.didMove(toParentViewController: parent)
if parent == nil {
} else {
}
}
Edited:
ChildViewController
override func didMove(toParentViewController parent: UIViewController?) {
super.didMove(toParentViewController: parent)
if parent == nil {
NotificationCenter.default.post(name: NSNotification.Name.init("Post"), object: nil)
} else {
}
}
ParentViewController
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
NotificationCenter.default.addObserver(self, selector: #selector(self.handler(notification:)), name: NSNotification.Name.init(rawValue: "Post"), object: nil)
}
func handler(notification: Notification) {
let alertController = UIAlertController(title: "Hello", message: nil, preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
self.present(alertController, animated: true, completion: nil)
}
This is works but with a problem like so:
Warning: Attempt to present on while a presentation is in progress!
Therefore I don't recommended. Good luck