views:

320

answers:

1

Hi

I have an UINavigationController which the user navigates with. When pushing a specific UIViewController onto the navigation stack, a "settings" button appear in the navigationBar. When the user clicks this button I would like to flip the current view/controller, i.e. everything on screen, including the navigationBar, over to a settings view.

So I have a SettingsViewController which I would like to flip to from my CurrentViewController that lives on a navigationController stack.

I get all kinds of strange behavior trying to do this, the UIViews belonging to the SettingsViewController will start to animate, sliding into place, the navigationButtons moves around, nothing acts as I would think.

-(void)settingsHandler {

    SettingViewController *settingsView = [[SettingViewController alloc] init];

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:1.0];
    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight
                           forView:self.navigationController.view
                            cache:YES];

    [self.navigationController.view addSubview:settingsView.view];

    [UIView commitAnimations];

}

The above results in the views flipping correctly, but the subviews of the SettingsViewController are all positioned in (0, 0) and after the transition, they 'snap' into place?

Is it because I instantiate and add my subviews in viewDidLoad, like this?

- (void)viewDidLoad {

    UIImageView *imageBg = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
    [imageBg setImage:[UIImage imageNamed:@"background.png"]];
    [self.view addSubview:imageBg];
    [imageBg release];

    SettingsSubview *switchView = [[SettingsSubview alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
    [self.view addSubview:switchView];
    [switchView release];
    [super viewDidLoad];
}

1: How should I correctly do the "flip" transition, from within the UIViewController in the UINavigationController, to a new UIViewController and subsequently from the new UIViewController and back to the "original" UIViewController residing on the UINavigationControllers stack?

2: Should I use a different approach, than the "viewDidLoad" method, when instantiating and adding subviews to a UIViewController?

-question 2 is more of a "best practice" thing. I have seen different ways of doing it and I am having trouble either finding or understanding the life-cycle documentation and the different threads and posts on the subject. I am missing the "best practice" examples.

Thank You very much for any help given:)

+1  A: 

If you want to create your view hierarchy programmatically, the place to do it is in -loadView. To do so you must create the view yourself, add all of its subviews, and then assign it to the view property, like this:

- (void)loadView {
    UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];

    UIImageView *imageBg = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
    [imageBg setImage:[UIImage imageNamed:@"background.png"]];
    [containerView addSubview:imageBg];
    [imageBg release];

    SettingsSubview *switchView = [[SettingsSubview alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 460.0f)];
    [containerView addSubview:switchView];
    [switchView release];

    self.view = containerView;
    [containerView release];
}

It helps to understand the context in which this method gets called, and how it behaves by default. The first time the view property of a UIViewController is accessed, the default getter method calls -loadView to lazy-load the view. The default implementation of -loadView loads the view from a nib if one was specified. Otherwise it creates a plain UIView object and sets that as the controller's view. By overriding this method, you can ensure that your view's hierarchy will be fully formed the first time it is accessed.

-viewDidLoad should be used for any subsequent setup that needs to occur after the view hierarchy is fully loaded. This method will get called whether the view is loaded from a nib or constructed programmatically in loadView.

cduhn
Thank you cduhn. That was a very good explanation and perfect example.
RickiG