views:

1760

answers:

2

Hi,

I have a view with a back button managed with a navigation controller and I want to check if a file has been saved when the user click on the back button. If the file has been saved you go back in the previous view, else a uialertview ask you if you want to save the file or not.

So I did that but the view disapear and the alertview appear after.

-(void)viewWillDisappear:(BOOL)animated {
if(!self.fileSaved){
 UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Save the file?"  delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
 [alert show];
 [alert release];
}
}

- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
{
switch (buttonIndex) {
    case 0:
  NSLog(@"NO");
  break;
 case 1:
  NSLog(@"yes");
  break;
 default:
  break;
}
}
+1  A: 

When viewWillDisappear is called, it's already too late. You should intercept the back button earlier on. I have never done it, but my suggestion is to set the delegate on the navigationBar property in your viewDidAppear method:

// save the previous delegate (create an ivar for that)
prevNavigationBarDelegate = self.navigationController.navigationBar.delegate;

self.navigationController.navigationBar.delegate = self;

Don't forget to set it back in viewWillDisappear:

self.navigationController.navigationBar.delegate = prevNavigationBarDelegate;

Then intercept the shouldPopItem method:

- (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item {
     if(!self.fileSaved) {
         UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:@"Save the file?"  delegate:self cancelButtonTitle:@"No" otherButtonTitles:@"Yes",nil];
         [alert show];
         [alert release];

         return NO;
     }

   if ([prevNavigationBarDelegate respondsToSelector:@selector(navigationBar:shouldPopItem:)]) 
      return [prevNavigationBarDelegate navigationBar:navigationBar shouldPopItem:item];

   return YES; 
}

And in the YES handler for the dialog, manually pop the controller:

[self.navigationController popViewController:YES];
Philippe Leybaert
Sounds logical, but you should probably save the current navigation bar delegate before overwriting it, reset it after you've decided to pop yourself, and maybe even pass through the `navigationBar:shouldPopItem:` call to the old delegate (if not nil) before showing your alert.
pix0r
The alertview doesn't appear with this code
Mathieu
@Mathieu: Is the method shouldPopItem called? If not, you may have to set the delegate in the viewDidAppear method instead of the init method. pix0r's comment is also valid. I'll update my answer to reflect that.
Philippe Leybaert
The shouldPopItem is not called either if I set the delegate in the viewDidAppear or viewDidLoad or in the init method
Mathieu
A: 

You must subclass UINavigationController for this to work. Then override - (BOOL)navigationBar:(UINavigationBar *)navigationBar shouldPopItem:(UINavigationItem *)item . You should set up a custom Delegate protocol that your view controllers adopt and, if you allow it to pop, call your [super navigationBar shouldPopItem:], else, return NO to the above method.

nobre