开发者

How to trap the back button event

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
    My开发者_如何学运维ViewController *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");
}


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];
    ...
}


It has been a while since this was asked, but I just tried to do this myself. I used a solution similar to Zoran's, however instead of using a flag I did this:

- (void)viewWillDisappear: (BOOL)animated
{
    [super viewWillDisappear: animated];
    if (![[self.navigationController viewControllers] containsObject: self])
    {
        // the view has been removed from the navigation stack, back is probably the cause
        // this will be slow with a large stack however.
    }
}

I think it bypasses the issues with flags and IMO is cleaner, however not as efficient (if there are lots of items on the navigation controller).


In my opinion the best solution.

- (void)didMoveToParentViewController:(UIViewController *)parent
{
    if (![parent isEqual:self.parentViewController]) {
         NSLog(@"Back pressed");
    }
}

But it only works with iOS5+


I use this code:

- (void) viewWillDisappear:(BOOL)animated {

   if ([self.navigationController.viewControllers indexOfObject:self] == NSNotFound)
   {
      // your view controller already out of the stack, it meens user pressed Back button
   }
}

But this is not actual when user presses tab bar button and pops to root view controller at one step. For this situation use this:

   [[NSNotificationCenter defaultCenter] addObserver:self
                                            selector:@selector(viewControllerChange:)
                                                name:@"UINavigationControllerWillShowViewControllerNotification"
                                              object:self.navigationController];


- (void) viewControllerChange:(NSNotification*)notification {

   NSDictionary* userInfo = [notification userInfo];

   if ([[userInfo objectForKey:@"UINavigationControllerNextVisibleViewController"] isKindOfClass:[<YourRootControllerClass> class]])
   { 
      // do your staff here
   }
}

Don't forget then:

   [[NSNotificationCenter defaultCenter] removeObserver:self
                                                   name:@"UINavigationControllerWillShowViewControllerNotification"
                                                 object:self.navigationController];


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


{
    UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:@"back"
                                                                   style:UIBarButtonItemStyleBordered 
                                                                  target:self                                                                             
                                                                  action:@selector(handleBack:)];
    self.navigationItem.leftBarButtonItem = backButton;
    [backButton release];
    [self filldata];
    [super viewDidLoad];
}

just replace backBarButtonItem with leftBarButtonItem


Simply use viewDidDisappear instead. It will be perfectly called in any scenario.

We are basing your lifecycle management on viewDidAppear and viewDidDisappear. If you know Android: the both are comparable to onResume and onPause methods. But there is a difference when it comes to locking the screen or pressing the homebutton on iOS.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜