views:

3210

answers:

7

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

I've been able to create navigation view's and programatically 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 achive 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 dont seem to understand enough about the relationships and initialisation procedure between UIViewController/UIView objects to achive this programatically.

A: 

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.

Is it possible to do this without the Navigation View Bar at the top? If possible I want to be able to do this with just a standard UIView object.
Akusete
+3  A: 

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.

Ben Gottlieb
I must be missing something becuase whenever I try to do use that method I get runtime exceptions. I'll keep reading.
Akusete
+7  A: 

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];
davidavr
I actually just found an example doing exactly this and was on my way to come answer my own question. Thanks.
Akusete
A: 

Hi Akusete,

Can you please give us the link to the example you found, or explain a little bit in more details. I confrunt with the same question.

Thanks, Alpar

I've added an answer with a link
Akusete
A: 

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.

Akusete
A: 

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

A: 

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

Wolfgang Schreurs