1

I need to show an UIAlertView before a user leaves a certain view, either by tapping a 'back' navigation bar button or by tapping one of the tab items in the tab bar I have, in order to ask him for confirmation. It would be a two-button alert, a 'Cancel' one to stay in the view, and an 'Accept' one to leave. I need to do this because I have to make the user aware that unsaved changes will be lost if leaving.

I tried to do this by creating and showing the alert view in the viewWillDisappear: method:

- (void)viewWillDisappear:(BOOL)animated
{

   UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Exit", @"")
                                                    message:NSLocalizedString(@"Are you sure you want to leave? Changes will be discarded", @"")
                                                   delegate:self
                                          cancelButtonTitle:NSLocalizedString(@"Cancel", @"")
                                          otherButtonTitles:NSLocalizedString(@"Accept", @""), nil];

   [alertView show];

   [super viewWillDisappear:animated];
}

But the view is pop anyway, and the alert view is shown after that and app crashes since its delegate is the view controller that has been already pop from the navigation stack... I don't find the way to solve this scenario, can anybody help me?

Thanks!

AppsDev
  • 11,441
  • 20
  • 81
  • 163
  • 1
    You need to make all of the buttons custom and handle the actions yourself (or add a transparent view over them to block touches and handle the touches, something like that). – Wain Oct 06 '13 at 15:53

2 Answers2

2

Showing the alert view when viewWillDissapear won't work, because the view is already dissapearing, it's on its way to be removed.

What you can do, is add yourself a custom action when the back button is pressed, then you decide what to do when the back button is pressed, you can show the alert view, and then in one of the buttons procedd to dismiss the view, something like this:

- (id)init {
    if (self = [super init]) {
    self.navigationItem.backBarButtonItem.target = self;
    self.navigationItem.backBarButtonItem.action = @selector(backButtonPressed:);
  }
    return self;
}

Then show the alert view when the back button is pressed:

-(void)backButtonPressed:(id)sender
 {
     UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Exit", @"") message:NSLocalizedString(@"Are you sure you want to leave? Changes will be discarded", @"") delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel", @"") otherButtonTitles:NSLocalizedString(@"Accept", @""), nil];      
    [alertView show];           
}

Now, when the confirmation button in the alert view is pressed, just call:

[self.navigationController popViewControllerAnimated:YES];

Or do nothing if the user cancels

Antonio MG
  • 20,166
  • 3
  • 40
  • 62
  • This doesn't work for me, since I had to define the back button in the view controller that pushes the one where I need to show the alert, because I had to customize the label of such back button... – AppsDev Oct 06 '13 at 17:01
  • I dont understand, you cant customize it or you can? – Antonio MG Oct 06 '13 at 17:10
  • Yes, I actually created an `UIBarButtonItem` in the parent view controller and set it as back button for the view controller where I need the alert just before pushing it... I don´t know if I'm explanining myself properly – AppsDev Oct 06 '13 at 17:13
  • Antonio is suggesting that when you create the `UIBarButtonItem` you set the action on it – benuuu Oct 06 '13 at 17:15
  • Thanks, that's what I meant – Antonio MG Oct 06 '13 at 17:16
  • But I create it in the parent view controller... I've tried setting the target to the child view controller and the `@selector` calling a method in the child as well, but it is not called... – AppsDev Oct 06 '13 at 17:17
1

I would be tempted to move the data manipulation you're trying to protect into a modal view controller and handle the validation on whatever action you choose to have dismiss the modal presentation. To me, that's the point of modal: something that has to be completed before interacting with the rest of the app.

Phillip Mills
  • 30,195
  • 4
  • 39
  • 55