I have a UINavigationController with a root view controller and then I push a UIViewController onto the navigation controller's stack. When the user taps the backBarButtonItem I'd like to be able to have an alert view pop up if there are certain conditions met and cancel the pop of the view controller. For example, the user can make certain selections but some combination of them may be invalid so I want to notify them to make changes.
I know that I can prevent the user from making an invalid combination or have an alert view pop up when the invalid combination is selected but I'd rather not do that. The user may be changing selections and may be aware that a certain combination is invalid but I'd rather let them select something that makes the combination invalid then go change something else (and notify them if they haven't made changes before trying to go to the previous screen). For example, if I prevent them from selecting something that makes an invalid combination then they may have to scroll up on a screen, change something, then scroll back down instead of making a selection then scrolling up and changing something.
Using viewWillDisappear:
doesn't work because, although I can produce an alert view, I cannot figure out a way to prevent the pop from occurring. The alert view displays but the view controller still pops and they are back to the root view controller (with the alert view displaying).
Is there a way to prevent the pop from occurring? If not, is this something worth filing a bug report about or is this unnecessary and/or esoteric?
The gesture recognizer responsible for popping the top view controller off the navigation stack.
NavController manages app navigation within a NavHost . Apps will generally obtain a controller directly from a host, or by using one of the utility methods on the Navigation class rather than create a controller directly. Navigation flows and destinations are determined by the navigation graph owned by the controller.
In addition, you can check for UINavigationController and ask for its topViewController or even check for UITabBarController and ask for selectedViewController . This will get you the view controller that is currently visible to the user.
You can replace the back button with your own that calls the method you want in loadView
cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel"
style:UIBarButtonItemStyleBordered
target:self
action:@selector(onCancelButtonSelected:)];
self.navigationItem.leftBarButtonItem = cancelButton;
then later
-(void)onCancelButtonSelected:(id)sender {
if (!hasSavedProduct)
{
cancelAlert = [[UIAlertView alloc] initWithTitle:@"Product not saved"
message:@"Exit without saving?"
delegate:self
cancelButtonTitle:@"Exit"
otherButtonTitles:@"Save",
nil];
[cancelAlert show];
[cancelAlert release];
}
then let them go
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if ([cancelAlert isEqual:actionSheet])
{
if (buttonIndex == 0)
{
NSLog(@"Fine. Exiting without saving");
[self.navigationController popViewControllerAnimated:YES];
}
else
{
NSLog(@"Save here");
}
}
This sounds like something more appropriate for a Modal View Controller than it is for a View Controller on a Navigation stack.
If you're married to doing it on the stack though, it'd be nice if you could do this with UINavigationControllerDelegate, but you can't.
Is it possible to set the Back button to disabled, until the entries are valid? Perhaps when the user tries to enter something, but it's invalid, near the top of the View you have a Label animate into place with red text that tells the user they need to fix it. Meanwhile the back button is disabled and it's re-enabled after they make corrections.
Or get really creative with how your UI controls work to ensure that the user can never enter bad data.
Let them go back, just don't save anything unless it's completely valid. That's typically the approach Apple takes.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With