Skip to main content

UINavigationController: Hiding Back Button on One View Hides it For All Views


I have a UINavigationController that contains 3 UIViewControllers on the stack.




View A - is the root
View B - is pushed by View A and has `self.navigationItem.hidesBackButton = YES;`
View C - is pushed by View B and has `self.navigationItem.hidesBackButton = NO;`



View C does not show the back button, even though I have hidesBackButton set to NO. How can I resolve this?


Source: Tips4all
Source: Tips4allSource: CCNA FINAL EXAM

Comments

  1. Update
    A possible bug in 4.2 as it works till 4.1 sdks

    I have tried this and mine is working perfectly. I am just posting the implementation of B view controller (BVC) and C view controller (CVC). My initial guess is that you are not setting the title of BVC in viewDidLoad.

    @implementation BVC


    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.title = @"I am B";
    }


    - (void) viewWillAppear:(BOOL)animated{
    self.navigationItem.hidesBackButton = YES;
    }

    - (IBAction)pushB:(UIButton *)sender{
    CVC *cvc = [[CVC alloc] initWithNibName:@"CVC" bundle:nil];
    [self.navigationController pushViewController:cvc animated:YES];
    [cvc release];
    }
    @end

    @implementation CVC

    - (void) viewWillAppear:(BOOL)animated{
    self.navigationItem.hidesBackButton = NO;
    }
    @end

    ReplyDelete
  2. I think you have to set that property before you push or pop a view controller to affect the next view controller, setting it for the current viewcontroller in viewWillAppear is too late.

    Edit: this looks like a bug in 4.2! The back button remains hidden both in the 4.2 simulator and on the device with 4.2, but it works in the 3.2, 4.1, and 4.0 simulators!

    Here's the code where when pushing a VC with a hidden back button:

    - (IBAction) goto2nd
    {
    SecondVC *vc = [[[SecondVC alloc] initWithNibName:@"SecondVC" bundle:nil] autorelease];
    vc.navigationItem.hidesBackButton = YES;
    [self.navigationController pushViewController:vc animated:YES];
    }


    That is all that should be needed, each VC has its own navigationItem, it's not a global setting, so you don't need to bother undoing it to restore the back button (at least when popping back to a VC where it is set to "NO").

    ReplyDelete
  3. The solution for this problem is somewhat tricky..just try it it will surely work since even I faced the same problem.

    First set Navigation title in viewWillAppear.

    - (void)viewWillAppear:(BOOL)animated
    {
    [super viewWillAppear:animated];
    self.navigationItem.title = @"SET YOUR TITLE";
    }


    When you are navigating to other page just set your navigation title to null.This will not show you any button on top.Since you can get rid of writing
    self.navigationItem.hidesBackButton = YES; everytime.

    - (IBAction)pushB:(UIButton *)sender
    {
    SecondVC *vc = [[[SecondVC alloc] initWithNibName:@"SecondVC" bundle:nil] autorelease];
    self.navigationItem.title = @"";
    [self.navigationController pushViewController:vc animated:YES];
    [vc release];
    }

    ReplyDelete
  4. Here's a workaround that I'm using successfully on 4.3.

    Instead of hiding the back button, set the left bar button view to an empty view:

    UIView *tmpView = [[UIView alloc] initWithFrame:CGRectZero];
    UIBarButtonItem *tmpButtonItem = [[UIBarButtonItem alloc] initWithCustomView:tmpView];
    [tmpView release];
    self.navigationItem.leftBarButtonItem = tmpButtonItem;
    [tmpButtonItem release];


    To restore the back button, just set the left bar button item to nil:

    [self.navigationItem setLeftBarButtonItem:nil animated:YES];


    Update: It appears as if the bug is gone in 4.3.

    Note: Even though the bug seems to be fixed, I prefer the "empty view" technique because it allows the disappearance and reappearance of the back button to be animated.

    ReplyDelete
  5. When you go back (however it is you're doing it), reset the hidesBackButton property to YES. For example, in your viewWillAppear: method, do something like

    @implementation SomeViewController

    - (void) viewWillAppear:(BOOL)animated {
    self.navigationController.navigationItem.hidesBackButton = YES;
    [super viewWillAppear:animated];
    }

    @end


    I figure it'd be as simple as that, but I could be wrong. The navigation item is owned by the UINavigationController, after all, so it makes sense to me that changes made to it will not be saved/restored depending on which UIViewController is in the UINavigationController's stack.

    ReplyDelete
  6. I'm running the same issue and it's only happening on the iOS 4.2 simulator, so probably it's a bug on that version.

    Reedit:

    Try with this, it worked for me:

    - (void)viewDidAppear:(BOOL)animated {

    [super viewDidAppear:animated];
    self.navigationItem.hidesBackButton = NO;
    }

    ReplyDelete
  7. Use the UINavigationControllerDelegate method -navigationController:willShowViewController:animated:. You will implement this in view controller A and view controller B. In A you will set -hidesBackButton: to YES and alternatively to NO in view controller B.

    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
    viewController.hidesBackButton = YES;
    }

    ReplyDelete
  8. You can also use following sample code;

    - (void) viewWillAppear:(BOOL)animated{
    self.navigationItem.hidesBackButton = YES;
    }

    - (void) viewWillDisappear:(BOOL)animated{
    self.navigationItem.hidesBackButton = NO;
    }

    ReplyDelete
  9. If your view heirarchy is really such that View B should not show a back button but View C should, then the simplest way to get around this is to refactor your heirarchy. I'm thinking of the following alternative:

    View A calls presentModalViewController:animated: on View B*, a UINavigationController whose view property is View B. View B* pushes View C onto its navigation stack in response to an event (or otherwise) from View B. If you need to jump back to
    View A quickly then call dismissModalViewControllerAnimated: on View A. If you want to keep the state of View B* and C in memory then you could also keep another pointer to View B* somewhere so it doesn't go away when dismissed.

    ReplyDelete

Post a Comment

Popular posts from this blog

Why is this Javascript much *slower* than its jQuery equivalent?

I have a HTML list of about 500 items and a "filter" box above it. I started by using jQuery to filter the list when I typed a letter (timing code added later): $('#filter').keyup( function() { var jqStart = (new Date).getTime(); var search = $(this).val().toLowerCase(); var $list = $('ul.ablist > li'); $list.each( function() { if ( $(this).text().toLowerCase().indexOf(search) === -1 ) $(this).hide(); else $(this).show(); } ); console.log('Time: ' + ((new Date).getTime() - jqStart)); } ); However, there was a couple of seconds delay after typing each letter (particularly the first letter). So I thought it may be slightly quicker if I used plain Javascript (I read recently that jQuery's each function is particularly slow). Here's my JS equivalent: document.getElementById('filter').addEventListener( 'keyup', function () { var jsStart = (new Date).getTime()...

Is it possible to have IF statement in an Echo statement in PHP

Thanks in advance. I did look at the other questions/answers that were similar and didn't find exactly what I was looking for. I'm trying to do this, am I on the right path? echo " <div id='tabs-".$match."'> <textarea id='".$match."' name='".$match."'>". if ($COLUMN_NAME === $match) { echo $FIELD_WITH_COLUMN_NAME; } else { } ."</textarea> <script type='text/javascript'> CKEDITOR.replace( '".$match."' ); </script> </div>"; I am getting the following error message in the browser: Parse error: syntax error, unexpected T_IF Please let me know if this is the right way to go about nesting an IF statement inside an echo. Thank you.