tags:

views:

2048

answers:

2

I have a UITableViewController that launches a UIViewController and I would like to trap whenever the back button is pressed in the child controller, which is the class that derives from 'UIViewController'. I can change the Back Button title but setting the target & action values when setting the backBarButtonItem seems to get ignored. What's a way to receiving some kind of notification that the Back button was tapped?

- (void)showDetailView 
{
    // How I'm creating & showing the detail controller
    MyViewController *controller = [[MyViewController alloc] initWithNibName:@"MyDetailView" bundle:nil]; 

    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"Pages"
          style:UIBarButtonItemStyleBordered 
          target:self          
          action:@selector(handleBack:)];

    self.navigationItem.backBarButtonItem = backButton;
    [backButton release];

    [self.navigationController pushViewController:controller animated:animated];
    [controller release];

}   

- (void)handleBack:(id)sender
{
    // not reaching here
    NSLog(@"handleBack event reached");
}
A: 

You can make your own button and place it as the leftBarButtonItem. Then have it call your method where you can do whatever, and call [self.navigationController popViewController... yourself

coneybeare
the 'leftBarButtonItem' won't show the same button style with the sideways looking triangle. Instead I think the button will be square. Is there a way to make it look like the typical backbutton as well as trap the event?
Alexi Groove
You can create your own left arrow image if you know the width of your button text -- or you could create it programmatically, mimicking what Apple does.
coneybeare
+2  A: 

You can implement the viewWillDisappear method of UIViewController. This gets called when your controller is about to go away (either because another one was pushed onto the navigation controller stack, or because the 'back' button was pressed).

To determine whether the view is disappearing because of the back button being pressed, you can use a custom flag that you set wherever you push a new controller onto the navigation controller, like shown below

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if (viewPushed) {
        viewPushed = NO;   // Flag indicates that view disappeared because we pushed another controller onto the navigation controller, we acknowledge it here
    } else {
        // Here, you know that back button was pressed
    }   
}

And wherever you push a new view controller, you would have to remember to also set that flag...

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    viewPushed = YES;
    [self.navigationController pushViewController:myNewController animated:YES];
    ...
}
Zoran Simic
How can you know that the view didn't disappear because some other button invoked a child view? I want to know only when the "Back" button is pressed.
Alexi Groove
In cases like this, I set a flag in didSelectRowAtIndexPath: (where you usually push a new controller onto the navigation controller). viewWillDisappear can then inspect that flag and deduce whether the back button was pressed or not
Zoran Simic
That still doesn't address the problem Justin pointed out; With your flag you will know how the view came into existence, but that doesn't mean that's the only way it will disappear.
Kelso.b
It does, because you're in control of what gets pushed onto the navigation controller. If you do it right (ie, you don't forget any cases), the only case left where your flag isn't set and your view is disappearing is when the user pressed the back button. This works great for me.
Zoran Simic