Akusete
Akusete

Reputation: 10794

Programmatically Switching Views in Cocoa Touch

How would one change the view on the screen programmatically in an iPhone app?

I've been able to create navigation view's and programmatically push/pop them to produce this behaviour, but if I wanted to simply change the current view (not using a UINavigation controller object), what is the neatest way to achieve this?

A simple example, imagine an application with a single button, when pressed will display a new view, or possibly one of multiple views depending on some internal state variable.

I have yet to see any examples that attempt to do this, and I don't seem to understand enough about the relationships and initialisation procedure between UIViewController/UIView objects to achieve this programmatically.

Upvotes: 7

Views: 6559

Answers (7)

Ben Gottlieb
Ben Gottlieb

Reputation: 85522

You'll want to explore -[UIView addSubview:] and -[UIView removeFromSuperview]. Your base window is a UIView (descendant), so you can add and remove views to it.

Upvotes: 3

Ronaldo Faria Lima
Ronaldo Faria Lima

Reputation: 429

This hint is said on Apple's documentation, but no importance is given to it. I found myself struggling to understand it and it is quite straightforward.

Simply change the main window's rootViewController property to whatever view controller that owns the view hierarchy you want to display. This is simple like that. As soon as the property is updated, the entire window content changes to the new view's contents.

Upvotes: 0

Wolfgang Schreurs
Wolfgang Schreurs

Reputation: 11834

You could use the following approach:

BaseView.h - all other views inherit from this view:

@interface BaseView : UIView {}
@property (nonatomic, assign) UIViewController *parentViewController;
@end

BaseView.m

@implementation BaseView
@synthesize parentViewController;

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        // Initialization code
    }
    return self;
}

- (void)dealloc {
    [self setParentViewController:nil];
    [super dealloc];
}

@end

Other views can inherit from BaseView. Their code should be a bit like the following:

@implementation FirstView

- (id)initWithFrame:(CGRect)frame {
    if ((self = [super initWithFrame:frame])) {
        [self setBackgroundColor:[UIColor yellowColor]];

        UIButton *button1 = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 30.0f)];
        [button1 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button1 setBackgroundColor:[UIColor whiteColor]];
        [button1 setCenter:CGPointMake(160.0f, 360.0f)];
        [button1 setTitle:@"Show Second View" forState:UIControlStateNormal];
        [button1 addTarget:self action:@selector(switchView:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button1];
        [button1 release];      

        UIButton *button2 = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 200.0f, 30.0f)];
        [button2 setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [button2 setBackgroundColor:[UIColor whiteColor]];
        [button2 setCenter:CGPointMake(160.0f, 120.0f)];
        [button2 setTitle:@"Show Sub View" forState:UIControlStateNormal];
        [button2 addTarget:self action:@selector(showView:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button2];
        [button2 release];              
    }

    return self;
}

- (void)showView:(id)sender {
    if (viewController == nil) {
        viewController = [[SubViewController alloc] initWithNibName:nil bundle:nil];        
    }

    [self addSubview:viewController.view];
}

- (void)switchView:(id)sender {
    SecondView *secondView = [[SecondView alloc] initWithFrame:self.frame];
    [self.parentViewController performSelector:@selector(switchView:) withObject:secondView];
    [secondView release];
}

- (void)dealloc {
    [viewController release];
    [super dealloc];
}

@end

Finally you'll need 1 UIViewController for all views. The switchView: method will be called to change the current view. The code for the UIViewController could be something like this:

@implementation ViewController

- (void)loadView {
    FirstView *firstView = [[FirstView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 480.0f)];    
    [firstView setParentViewController:self];
    [self setView:firstView];
    [firstView release];
}

- (void)switchView:(BaseView *)newView {
    [newView setParentViewController:self];
    [self retain];
    [self setView:newView];
    [self release];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
    [super viewDidUnload];
}  

- (void)dealloc {
    [super dealloc];
}

@end

You can download an example app here (within the next hour): http://dl.dropbox.com/u/6487838/ViewSwitch.zip

Upvotes: 0

Andy
Andy

Reputation:

The NavBarDemo is interesting but in the end, the modalView is just another view getting pushed and popped off the stack, from what I can tell.

What about cases like the maps application, where the map view switches to a table view listing search options when the user starts typing an address? Are both these views already init'ed at launch, and the search results table view just set to visibility 0 and when you type, its switched to 1, or is it actually loaded on the touchUpInside event of the text field?

I'll try messing with UIView addSubview to recreate this action and post my results

Upvotes: 0

Akusete
Akusete

Reputation: 10794

I've found an example program which uses ModalView's to display views without nesting them as NavigatorControlView's.

iPhone Nav Bar Demo

The example link above, uses a modalView for the information link. And also uses navigation links for the table view links.

Upvotes: 0

davidavr
davidavr

Reputation: 14203

I use presentModalViewController:animated: to bring up a settings view from my main window's UIViewController and then when the user presses "done" in the settings view I call dismissModalViewControllerAnimated: from the settings view (reaching back to the parent view) like this:

[[self parentViewController] dismissModalViewControllerAnimated:YES];

Upvotes: 8

Bill Heyman
Bill Heyman

Reputation:

How about pushing a generic UIView into the UINavigationController?

When you want one particular view shown, simply add it as a subview to that previously pushed UIView. When you want to change views, remove the previous subview and add the new one.

Upvotes: 0

Related Questions