Sunday, June 9, 2013

UINavigationBar setBarStyle example in Objective C (iOS).


UINavigationBar setBarStyle

The appearance of the navigation bar.

@property(nonatomic, assign) UIBarStyle barStyle

Discussion of [UINavigationBar setBarStyle]
See UIBarStyle for possible values. The default value is UIBarStyleDefault.

It is permissible to set the value of this property when the navigation bar is being managed by a navigation controller object.

UINavigationBar setBarStyle example.
irstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:fvc];
[fvc release];

navcon.navigationBar.barStyle = UIBarStyleBlackTranslucent;

[self.window addSubview:navcon.view];
[self.window makeKeyAndVisible];

return YES;

Example of [UINavigationBar setBarStyle].
The Apple Documentation says to use the following since UIBarStyleBlackTranslucent is deprecated:

navController.navigationBar.barStyle = UIBarStyleBlack;
navController.navigationBar.translucent = YES;
You could try shifting your view back in the correct place or try using the following:

navController.navigationBar.tintColor = [UIColor blackColor];
navController.navigationBar.translucent = YES;

UINavigationBar setBarStyle example.
In RootViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar setBarStyle:UIBarStyleDefault];
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"orangeNavigationBar.png"] forBarMetrics:UIBarMetricsDefault];
}
In TranslucentViewController

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

    [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
}

End of UINavigationBar setBarStyle example article.

UINavigationBar barStyle example in Objective C (iOS).


UINavigationBar barStyle

The appearance of the navigation bar.

@property(nonatomic, assign) UIBarStyle barStyle

Discussion of [UINavigationBar barStyle]
See UIBarStyle for possible values. The default value is UIBarStyleDefault.

It is permissible to set the value of this property when the navigation bar is being managed by a navigation controller object.

UINavigationBar barStyle example.
irstViewController *fvc = [[FirstViewController alloc] init];
UINavigationController *navcon = [[UINavigationController alloc] initWithRootViewController:fvc];
[fvc release];

navcon.navigationBar.barStyle = UIBarStyleBlackTranslucent;

[self.window addSubview:navcon.view];
[self.window makeKeyAndVisible];

return YES;

Example of [UINavigationBar barStyle].
The Apple Documentation says to use the following since UIBarStyleBlackTranslucent is deprecated:

navController.navigationBar.barStyle = UIBarStyleBlack;
navController.navigationBar.translucent = YES;
You could try shifting your view back in the correct place or try using the following:

navController.navigationBar.tintColor = [UIColor blackColor];
navController.navigationBar.translucent = YES;

UINavigationBar barStyle example.
In RootViewController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self.navigationController.navigationBar setBarStyle:UIBarStyleDefault];
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"orangeNavigationBar.png"] forBarMetrics:UIBarMetricsDefault];
}
In TranslucentViewController

- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];

    [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setBarStyle:UIBarStyleBlackTranslucent];
}

End of UINavigationBar barStyle example article.

UINavigationController UINavigationControllerHideShowBarDuration example in Objective C (iOS).


UINavigationController UINavigationControllerHideShowBarDuration

A global variable that specifies a preferred duration when animating the navigation bar.

extern const CGFloat UINavigationControllerHideShowBarDuration
Constants
UINavigationControllerHideShowBarDuration
This variable specifies the duration when animating the navigation bar. Note that this is a constant value, so it cannot be set.

UINavigationController UINavigationControllerHideShowBarDuration example.
[self.navigationController setNavigationBarHidden:YES animated:YES];
 [UIView transitionWithView:self.view
                   duration:UINavigationControllerHideShowBarDuration
                    options:UIViewAnimationOptionCurveLinear
                 animations:^
  {
   /* Put other animation code here ;) */
  }
                 completion:^(BOOL finished)
  {                                 
  }];

Example of [UINavigationController UINavigationControllerHideShowBarDuration].
- (void)pushViewControllerAfterAnimation:(UIViewController *)viewController animated:(BOOL)animated {
    [UIView transitionWithView:viewController.view
                      duration:UINavigationControllerHideShowBarDuration
                       options:UIViewAnimationCurveEaseOut
                    animations:^{
                        [self.navigationController setNavigationBarHidden:NO];    
                    }
                    completion:^(BOOL finished){
                        NSLog(@"animation finished");
                        [self pushViewController:viewController animated:animated];
                    }];
}

- (void)popViewControllerAfterAnimationAnimated:(BOOL)animated {
    [UIView transitionWithView:self.visibleViewController.view
                      duration:UINavigationControllerHideShowBarDuration
                       options:UIViewAnimationCurveEaseOut
                    animations:^{
                        [self.navigationController setNavigationBarHidden:YES];    
                    }
                    completion:^(BOOL finished){
                        NSLog(@"animation finished");
                        [self popViewControllerAnimated:animated];
                    }];
}

UINavigationController UINavigationControllerHideShowBarDuration example.
Only improvement would be setting anim duration to be consistent with other navigation controller animations:

    [UIView setAnimationDuration:UINavigationControllerHideShowBarDuration];

End of UINavigationController UINavigationControllerHideShowBarDuration example article.

UINavigationController setViewControllers animated example in Objective C (iOS).


UINavigationController setViewControllers animated

Replaces the view controllers currently managed by the navigation controller with the specified items.

- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated

Parameters of [UINavigationController setViewControllers animated]
viewControllers
The view controllers to place in the stack. The front-to-back order of the controllers in this array represents the new bottom-to-top order of the controllers in the navigation stack. Thus, the last item added to the array becomes the top item of the navigation stack.
animated
If YES, animate the pushing or popping of the top view controller. If NO, replace the view controllers without any animations.

Discussion of [UINavigationController setViewControllers animated]
You can use this method to update or replace the current view controller stack without pushing or popping each controller explicitly. In addition, this method lets you update the set of controllers without animating the changes, which might be appropriate at launch time when you want to return the navigation controller to a previous state.[UINavigationController setViewControllers animated]

If animations are enabled, this method decides which type of transition to perform based on whether the last item in the items array is already in the navigation stack. If the view controller is currently in the stack, but is not the topmost item, this method uses a pop transition; if it is the topmost item, no transition is performed. If the view controller is not on the stack, this method uses a push transition. Only one transition is performed, but when that transition finishes, the entire contents of the stack are replaced with the new view controllers. For example, if controllers A, B, and C are on the stack and you set controllers D, A, and B, this method uses a pop transition and the resulting stack contains the controllers D, A, and B.

UINavigationController setViewControllers animated example.
Finally I found the solution. The mistake was that the new top-level NavigationController has not been initialized and loaded properly until the animation is done. In my case, UserAssignmentsListViewController has a viewDidLoad method that will not be called until animation is done, but it sets the navigation title (here: a UIButton). Therefore the animation fails.

The solution is to refer to an already initialized view controller when it comes to pushing it to the stack. So initialize our top-level VC somewhere:

// initialize our top-level controller
ViewController* viewController2 = [[[ViewController alloc]
    initWithNibName:@"ViewController" bundle:nil] autorelease];
Then when pushing two or more VCs to the stack, the top level one is already initialized and the animation works (following the example from my original question):

NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack, too
[viewControllers addObject:self];

ViewController* viewController1 = [[[ViewController alloc]
    initWithNibName:@"ViewController" bundle:nil] autorelease];
[viewControllers addObject:viewController1];

if (someCondition == YES)
{
    [viewControllers addObject:viewController2];
}

[self.navigationController
    setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];

Example of [UINavigationController setViewControllers animated].
//Create view controller which confirms backup/restore complete
ConfirmationViewController *v = [[ConfirmationViewController alloc] init];

//Create array containing only root view controller and confirmation view controller
NSArray *viewControllers = [[NSArray alloc] initWithObjects:[self.navigationController.viewControllers objectAtIndex:0], v, nil];
[v release];

//Push the confirmation view controller so the user can see it
[self.navigationController pushViewController:v animated:YES];

//Set navigationController's viewControllers array in order to remove the intermediary view controllers. Back button now goes back to root viewController
[self.navigationController setViewControllers:viewControllers animated:YES];
[viewControllers release];

UINavigationController setViewControllers animated example.
[self performSelector: @selector(launchPhotoViewer)
                                   withObject: nil
                                   afterDelay: 0.1];

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PhotoTest1Controller* test = [[PhotoTest1Controller alloc] init];
        [navigationController pushViewController:test animated:NO];

        // Remove previous view the hard way
        NSArray* orig = [navigationController viewControllers];
        NSMutableArray* newa = [[NSMutableArray alloc] init];
        for (id i in orig)
        {
                [newa addObject:i];
        }
        [newa removeObjectAtIndex:[orig count]-2];
        [navigationController setViewControllers:(NSArray*)newa]; 

End of UINavigationController setViewControllers animated example article.

UINavigationController setViewControllers example in Objective C (iOS).


UINavigationController setViewControllers

Replaces the view controllers currently managed by the navigation controller with the specified items.

- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated

Parameters of [UINavigationController setViewControllers]
viewControllers
The view controllers to place in the stack. The front-to-back order of the controllers in this array represents the new bottom-to-top order of the controllers in the navigation stack. Thus, the last item added to the array becomes the top item of the navigation stack.
animated
If YES, animate the pushing or popping of the top view controller. If NO, replace the view controllers without any animations.

Discussion of [UINavigationController setViewControllers]
You can use this method to update or replace the current view controller stack without pushing or popping each controller explicitly. In addition, this method lets you update the set of controllers without animating the changes, which might be appropriate at launch time when you want to return the navigation controller to a previous state.[UINavigationController setViewControllers]

If animations are enabled, this method decides which type of transition to perform based on whether the last item in the items array is already in the navigation stack. If the view controller is currently in the stack, but is not the topmost item, this method uses a pop transition; if it is the topmost item, no transition is performed. If the view controller is not on the stack, this method uses a push transition. Only one transition is performed, but when that transition finishes, the entire contents of the stack are replaced with the new view controllers. For example, if controllers A, B, and C are on the stack and you set controllers D, A, and B, this method uses a pop transition and the resulting stack contains the controllers D, A, and B.

UINavigationController setViewControllers example.
Finally I found the solution. The mistake was that the new top-level NavigationController has not been initialized and loaded properly until the animation is done. In my case, UserAssignmentsListViewController has a viewDidLoad method that will not be called until animation is done, but it sets the navigation title (here: a UIButton). Therefore the animation fails.

The solution is to refer to an already initialized view controller when it comes to pushing it to the stack. So initialize our top-level VC somewhere:

// initialize our top-level controller
ViewController* viewController2 = [[[ViewController alloc]
    initWithNibName:@"ViewController" bundle:nil] autorelease];
Then when pushing two or more VCs to the stack, the top level one is already initialized and the animation works (following the example from my original question):

NSMutableArray* viewControllers = [NSMutableArray arrayWithCapacity:2];
// put us on the stack, too
[viewControllers addObject:self];

ViewController* viewController1 = [[[ViewController alloc]
    initWithNibName:@"ViewController" bundle:nil] autorelease];
[viewControllers addObject:viewController1];

if (someCondition == YES)
{
    [viewControllers addObject:viewController2];
}

[self.navigationController
    setViewControllers:[NSArray arrayWithArray:viewControllers] animated:YES];

Example of [UINavigationController setViewControllers].
//Create view controller which confirms backup/restore complete
ConfirmationViewController *v = [[ConfirmationViewController alloc] init];

//Create array containing only root view controller and confirmation view controller
NSArray *viewControllers = [[NSArray alloc] initWithObjects:[self.navigationController.viewControllers objectAtIndex:0], v, nil];
[v release];

//Push the confirmation view controller so the user can see it
[self.navigationController pushViewController:v animated:YES];

//Set navigationController's viewControllers array in order to remove the intermediary view controllers. Back button now goes back to root viewController
[self.navigationController setViewControllers:viewControllers animated:YES];
[viewControllers release];

UINavigationController setViewControllers example.
[self performSelector: @selector(launchPhotoViewer)
                                   withObject: nil
                                   afterDelay: 0.1];

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

PhotoTest1Controller* test = [[PhotoTest1Controller alloc] init];
        [navigationController pushViewController:test animated:NO];

        // Remove previous view the hard way
        NSArray* orig = [navigationController viewControllers];
        NSMutableArray* newa = [[NSMutableArray alloc] init];
        for (id i in orig)
        {
                [newa addObject:i];
        }
        [newa removeObjectAtIndex:[orig count]-2];
        [navigationController setViewControllers:(NSArray*)newa]; 

End of UINavigationController setViewControllers example article.

UINavigationController pushViewController animated example in Objective C (iOS).


UINavigationController pushViewController animated

Pushes a view controller onto the receiver’s stack and updates the display.

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated

Parameters of [UINavigationController pushViewController animated]
viewController
The view controller that is pushed onto the stack. This object cannot be an instance of tab bar controller and it must not already be on the navigation stack.
animated
Specify YES to animate the transition or NO if you do not want the transition to be animated. You might specify NO if you are setting up the navigation controller at launch time.

Discussion of [UINavigationController pushViewController animated]
The object in the viewController parameter becomes the top view controller on the navigation stack. Pushing a view controller results in the display of the view it manages. How that view is displayed is determined by the animated parameter. If the animated parameter is YES, the view is animated into position; otherwise, the view is simply displayed in place. The view is automatically resized to fit between the navigation bar and toolbar (if present) before it is displayed.[UINavigationController pushViewController animated]

In addition to displaying the view associated with the new view controller at the top of the stack, this method also updates the navigation bar and tool bar accordingly. In iOS 3.0 and later, the contents of the built-in navigation toolbar are updated to reflect the toolbar items of the new view controller. For information on how the navigation bar is updated, see “Updating the Navigation Bar.”

Important: In iOS 2.2 and later, if the object in the viewController parameter is already on the navigation stack, this method throws an exception. In earlier versions of iOS, the method simply does nothing.
UINavigationController pushViewController animated example.
- (void) viewDidAppear
{   
    [self performSelector:@selector(loginCheck:) withObject:nil afterDelay:0.5];
}   
- (void) loginCheck:(id)sender
{
    LoginViewController * lvc = [[LoginViewController alloc] init];
    //lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [lvc setDelegate:self];
    //[self presentModalViewController:lvc animated:YES];  
    [self.navigationController pushViewController:lvc animated:YES];  
}

Example of [UINavigationController pushViewController animated].
- (void)viewDidLoad {
[super viewDidLoad];
    UINavigationController *navigationController
navigationController = [[UINavigationController alloc] init];
[self.view addSubview:navigationController.view];  

switch (whichViewController) {
    case 1:
        viewController = [[xxxx alloc] init];          
        break;
    case 2:
        viewController = [[xxx1 alloc] init];          
        break;
    default:
        break;
}

[navigationController pushViewController:viewController animated:NO];
[viewController release];
}

UINavigationController pushViewController animated example.
- (void)ShowPageWithIMDevicePage:(id<IMDevicePage>)page {
    YourDelegate* delegate = (YourDelegate*)[[UIApplication sharedApplication] delegate];
    IPhonePage* pageVC = (IPhonePage*)page;
    [delegate.navigationController pushViewController:pageVC animated:YES];
}

End of UINavigationController pushViewController animated example article.

UINavigationController pushViewController example in Objective C (iOS).


UINavigationController pushViewController

Pushes a view controller onto the receiver’s stack and updates the display.

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated

Parameters of [UINavigationController pushViewController]
viewController
The view controller that is pushed onto the stack. This object cannot be an instance of tab bar controller and it must not already be on the navigation stack.
animated
Specify YES to animate the transition or NO if you do not want the transition to be animated. You might specify NO if you are setting up the navigation controller at launch time.

Discussion of [UINavigationController pushViewController]
The object in the viewController parameter becomes the top view controller on the navigation stack. Pushing a view controller results in the display of the view it manages. How that view is displayed is determined by the animated parameter. If the animated parameter is YES, the view is animated into position; otherwise, the view is simply displayed in place. The view is automatically resized to fit between the navigation bar and toolbar (if present) before it is displayed.[UINavigationController pushViewController]

In addition to displaying the view associated with the new view controller at the top of the stack, this method also updates the navigation bar and tool bar accordingly. In iOS 3.0 and later, the contents of the built-in navigation toolbar are updated to reflect the toolbar items of the new view controller. For information on how the navigation bar is updated, see “Updating the Navigation Bar.”

Important: In iOS 2.2 and later, if the object in the viewController parameter is already on the navigation stack, this method throws an exception. In earlier versions of iOS, the method simply does nothing.
UINavigationController pushViewController example.
- (void) viewDidAppear
{   
    [self performSelector:@selector(loginCheck:) withObject:nil afterDelay:0.5];
}   
- (void) loginCheck:(id)sender
{
    LoginViewController * lvc = [[LoginViewController alloc] init];
    //lvc.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
    [lvc setDelegate:self];
    //[self presentModalViewController:lvc animated:YES];  
    [self.navigationController pushViewController:lvc animated:YES];  
}

Example of [UINavigationController pushViewController].
- (void)viewDidLoad {
[super viewDidLoad];
    UINavigationController *navigationController
navigationController = [[UINavigationController alloc] init];
[self.view addSubview:navigationController.view];  

switch (whichViewController) {
    case 1:
        viewController = [[xxxx alloc] init];          
        break;
    case 2:
        viewController = [[xxx1 alloc] init];          
        break;
    default:
        break;
}

[navigationController pushViewController:viewController animated:NO];
[viewController release];
}

UINavigationController pushViewController example.
- (void)ShowPageWithIMDevicePage:(id<IMDevicePage>)page {
    YourDelegate* delegate = (YourDelegate*)[[UIApplication sharedApplication] delegate];
    IPhonePage* pageVC = (IPhonePage*)page;
    [delegate.navigationController pushViewController:pageVC animated:YES];
}

End of UINavigationController pushViewController example article.