Showing posts with label setViewControllers animated. Show all posts
Showing posts with label setViewControllers animated. Show all posts

Monday, June 10, 2013

UITabBarController setViewControllers animated example in Objective C (iOS).


UITabBarController setViewControllers animated

Sets the root view controllers of the tab bar controller.

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

Parameters of [UITabBarController setViewControllers animated]
viewControllers
The array of custom view controllers to display in the tab bar interface. The order of the view controllers in this array corresponds to the display order in the tab bar, with the controller at index 0 representing the left-most tab, the controller at index 1 the next tab to the right, and so on.
animated
If YES, the tab bar items for the view controllers are animated into position. If NO, changes to the tab bar items are reflected immediately.

Discussion of [UITabBarController setViewControllers animated]
When you assign a new set of view controllers at runtime, the tab bar controller removes all of the old view controllers before installing the new ones. When changing the view controllers, the tab bar controller remembers the view controller object that was previously selected and attempts to reselect it. If the selected view controller is no longer present, it attempts to select the view controller at the same index in the array as the previous selection. If that index is invalid, it selects the view controller at index 0.

This method also sets the value of the customizableViewControllers property to the contents of the viewControllers parameter.

UITabBarController setViewControllers animated example.
// generate an instance of the needed UIViewController
adminViewController *admin = [[adminViewController alloc] init];
admin.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"Admin" image:[UIImage imageNamed:@"admin.png"] tag:5];

// get the AppDelegate instance
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

// get the »viewControllers« array of the AppDelegates UITabbarController as mutable array
NSMutableArray *viewControllersArray = [NSMutableArray arrayWithArray:[[appDelegate tabBarController] viewControllers]];
// insert the UITabbarItem of the needed UIViewController
[viewControllersArray insertObject:admin atIndex:2];

// Finally tell the app delegates UITabbarController to set the needed viewControllers
[[appDelegate tabBarController] setViewControllers:viewControllersArray animated:NO];

Example of [UITabBarController setViewControllers animated].
Subclass UITabBarController

Override the - (void) loadView method and include the following code

MyCustomViewControllerOne* ctrl1 = [[[MyCustomViewControllerOne alloc] initWithNibName@"MyViewControllerOne" bundle: nil] autorelease];
UIViewController* ctrl2 = [[[UIViewController alloc] init] autorelease];
MyCustomControllerTwo* ctrl3 = [[[UIViewController alloc] initWithObject: myObj] autorelease];

ctrl1.title = @"First tab";
ctrl2.title = @"Second tab";
ctrl3.title = @"Third tab";

ctrl1.tabBarItem.image = [UIImage imageNamed:@"tab_image1.png"];
ctrl2.tabBarItem.image = [UIImage imageNamed:@"tab_image2.png"];
ctrl3.tabBarItem.image = [UIImage imageNamed:@"tab_image3.png"];

[self setViewControllers: @[ctrl1, ctrl2, ctrl3]];

UITabBarController setViewControllers animated example.
NSMutableArray* newArray = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers];
[newArray removeObjectAtIndex:0];
[self.tabBarController setViewControllers:newArray animated:YES];

End of UITabBarController setViewControllers animated example article.

Sunday, June 9, 2013

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.