3

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
let newBackButton = UIBarButtonItem(title: "<", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.save(sender:)))
self.navigationItem.leftBarButtonItem = newBackButton

This is working fine but I want the default back button image in it and not the custom title. How to do that ?

I tried following code as well :

self.navigationItem.backBarButtonItem?.action = #selector(ViewController.save(sender:))

...but the action is not performed, too.

Jay D
  • 3,263
  • 4
  • 32
  • 48
Nitesh
  • 1,564
  • 2
  • 26
  • 53

6 Answers6

5

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
    }
}
Amit Tandel
  • 883
  • 7
  • 16
2

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
        }
    }
}
1

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)

      }
ViJay Avhad
  • 2,684
  • 22
  • 26
0

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.

regetskcob
  • 1,172
  • 1
  • 13
  • 35
  • I need to display an alert when user press the back button. Alert will have button with "Yes" and "No". I tried it on viewWillDisappear but my alert was not presented on it – Nitesh Feb 08 '17 at 06:41
  • Added another option that should fit in your situation. – regetskcob Feb 08 '17 at 06:44
  • It is gets called when view is presented and every time on push, etc. I want it only on back. – Nitesh Feb 08 '17 at 09:19
  • @Nitesh you have to check whether the `viewController`that will be shown is the one you want to show the alert before and then you're done! – regetskcob Feb 08 '17 at 09:36
0

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
Community
  • 1
  • 1
Akaino
  • 1,025
  • 6
  • 23
0

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

Mannopson
  • 2,634
  • 1
  • 16
  • 32