I needed to create an application base with multiple view
controllers, and an easy method for switching between them. I came up
with a solution that passes messages via the App Delegate, and has a
parent View Controller that manages the sub-views.

The following code is the App Delegate:
MultiviewAppDelegate.h
#import <UIKit/UIKit.h>
@class MultiviewViewController;
@interface MultiviewAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MultiviewViewController *viewController;
}
@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet MultiviewViewController *viewController;
-(void) displayView:(int)intNewView;
@end
MultiviewAppDelegate.m
#import "MultiviewAppDelegate.h"
#import "MultiviewViewController.h"
@implementation MultiviewAppDelegate
@synthesize window;
@synthesize viewController;
-(void) displayView:(int)intNewView {
[viewController displayView:intNewView];
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
@end
Pretty basic stuff (almost exactly the default for the AppDelegate
template). The only addition is the displayView function, which
passes a message to the parent View Controller.
MultiviewViewController.h
#import <UIKit/UIKit.h>
@interface MultiviewViewController : UIViewController {
}
- (void) displayView:(int)intNewView;
@end
This has an internal displayView function which is called by the
AppDelegate.
MultiviewViewController.m
#import "MultiviewViewController.h"
#import "View01.h"
#import "View02.h"
@implementation MultiviewViewController
UIViewController *currentView;
- (void) displayView:(int)intNewView {
NSLog(@"%i", intNewView);
[currentView.view removeFromSuperview];
[currentView release];
switch (intNewView) {
case 1:
currentView = [[View01 alloc] init];
break;
case 2:
currentView = [[View02 alloc] init];
break;
}
[self.view addSubview:currentView.view];
}
- (void)viewDidLoad {
currentView = [[View01 alloc] init];
[self.view addSubview:currentView.view];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
doesn't have a superview
}
- (void)dealloc {
[currentView release];
[super dealloc];
}
@end
Now we just have to have multiple sub-views.
View01.h
#import <UIKit/UIKit.h>
@interface View01 : UIViewController {
}
@end
View01.m
#import "View01.h"
#import "MultiviewAppDelegate.h"
@implementation View01
- (void)goToTwo {
MultiviewAppDelegate *appDelegate = [[UIApplication
sharedApplication] delegate];
[appDelegate displayView:2];
}
- (void)viewDidLoad {
NSLog(@"load01");
UIButton *btnOne = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnOne.frame = CGRectMake(40, 40, 240, 30);
[btnOne setTitle:@"One!" forState:UIControlStateNormal];
[btnOne addTarget:self action:@selector(goToTwo)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnOne];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
doesn't have a superview
}
- (void)dealloc {
NSLog(@"dealloc01");
[super dealloc];
}
@end
The second view looks just like the first, but goes to "one"
instead of two.
View02.h
#import <UIKit/UIKit.h>
@interface View02 : UIViewController {
}
@end
View02.m
#import "View02.h"
#import "MultiviewAppDelegate.h"
@implementation View02
- (void)goToOne {
MultiviewAppDelegate *appDelegate = [[UIApplication
sharedApplication] delegate];
[appDelegate displayView:1];
}
- (void)viewDidLoad {
NSLog(@"load02");
UIButton *btnTwo = [UIButton buttonWithType:UIButtonTypeRoundedRect];
btnTwo.frame = CGRectMake(40, 40, 240, 30);
[btnTwo setTitle:@"Two!" forState:UIControlStateNormal];
[btnTwo addTarget:self action:@selector(goToOne)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnTwo];
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
doesn't have a superview
}
- (void)dealloc {
NSLog(@"dealloc02");
[super dealloc];
}
@end
And that's it! It seems like a lot, but it's a basic framework
that makes it easy to add in new views and navigate between them.
I created this to help me go between multiple screens built by
different developers that weren't working in the same environment. It
makes it easy to add the .m and .h file of a View Controller, and then
with some minor changes, be able to insert it into the navigation flow
of any application.
One caveat: if you have a timer, you need to invalidate it before
you call [appDelegate displayview:]. I've also been making it a habit
to set my objAccelerator.delegate = nil in the dealloc function of
each View Controller.
You must also have good memory management practices (release
everything you alloc!), because the dealloc is not just called when
the program terminates -- it's called every time you switch views.
Download the source
files here!
21 Comments
| |
|
06
May 2009
|
Lee Armstrong Great article!
If I was to start afresh and implement that code would I start with a Window application? And then add the views and corresponding xib files? |
|
07
May 2009
|
Jeffrey Berthiaume Actually, I started from a View-based Application (that I called "Multiview")... That way, MultiviewAppDelegate.h, MultiviewAppDelegate.m, MultiviewViewController.h, and MultiviewViewController.m are created automatically. I don't ever use xib files or Interface Builder -- I tend to prefer doing everything in code... |
|
27
Jun 2009
|
Jim I know this was a couple of months back but I'm just starting with iPhone development and was wondering if this method supported animation between views/controllers and if after OS 3.0 anything in the framework has since made working with multiple views/controllers easier? |
|
29
Jun 2009
|
Jeffrey Berthiaume No, I'm not transitioning between views using this framework. Also, as far as I know, OS 3.0 doesn't do anything different (API-wise) for managing views... |
|
21
Jul 2009
|
don Hi,
Can you please tell how to mix the view types as well?! like the
view 1 being core graphics using some nib,
view 2 being openGL es view
I am trying to put in opengl es in addmusic sample code, but am failing to figure it out. please help |
|
23
Jul 2009
|
prasad This is the best article I ever found.. good design, easily scalable and faster..
And I think the second "MultiviewAppDelegate.h" should be "MultiviewAppDelegate.m" in the code section.. :-) |
|
23
Jul 2009
|
Adam Hey, this code was really helpful. Thank you!
Also I have the same question that Don asked. I'm trying to figure out how to load in a UIView and a view using openGL. Its quite tricky, if you know of a good way please let me know! Thank you. |
|
23
Jul 2009
|
Adam Don, I figured out what you wanted to know. Add EAGLView.h and m to your project. Then in one of your views view did load put in:
EAGLView *background = [[EAGLView alloc]
initWithFrame:CGRectMake(0.0f, -20.0f, 320.0f, 470.0f)];
[background startAnimation];
background.animationInterval = 1.0 / 60.0;
[self.view addSubview:background];
[background release];
[super viewDidLoad];
Also add #import "EAGLView.h" to the top of the file.
Then in EAGLView.m replace init with coder for this function.
- (id) initWithFrame:(CGRect)frame
{
if((self = [super initWithFrame:frame])) {
CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[self layer];
eaglLayer.drawableProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES],
kEAGLDrawablePropertyRetainedBacking,
kEAGLColorFormatRGBA8,
kEAGLDrawablePropertyColorFormat, nil];
context = [[EAGLContext alloc]
initWithAPI:kEAGLRenderingAPIOpenGLES1];
if(context == nil) {
[self release];
return nil;
}
}
return self;
}
Give it a try and see if it works |
|
06
Aug 2009
|
David Sielert Excellent document exactly what I was looking for. Wish there were a way to steer away from using the integer associations with the views .. |
|
24
Sep 2009
|
Brent Chapman Do you know if there is any way to add a uitabviewcontroller to one of the sub views? I am having trouble finding a way to do this. |
|
26
Sep 2009
|
mauricio giraldo This is just what I was looking for. Thanks.
How would you manage this with NIBs. I already got everything set up with NIBs and they stay in memory throughout the whole app lifetime (consuming resources). dealloc/viewDidUnload never fires. |
|
27
Sep 2009
|
mauricio giraldo I have managed to make dealloc fire but the nib is still in memory. I have put a more detailed question (along with my implementation of your framework) here:
http://stackoverflow.com/questions/1482934/iphone-app-with-multiple-views-subviews-memory-is-not-being-deallocated |
|
09
Oct 2009
|
mauricio giraldo Hi
I did a NIB-based version of your framework. You can download it here: http://www.mauriciogiraldo.com/blog/2009/10/09/multiples-views-no-jerarquicas-en-iphone/ |
|
16
Oct 2009
|
Mike Looking at Adams comments regarding the EAGLView.h stuff. Has someone actually taken the OpenGLES Template and modified it so this works?
Several questions come to mind - are these change based on the Template? Will the work with the new 3.0 SDK?
I would love to see the full sample code of the 3.x sdk OpenGLES template modifed to work with this code. |
|
24
Nov 2009
|
Gary This is an excellent, and a very useful, tutorial. Thank you very much for putting this together.
I have managed to include the multiviewcontroller into a Tableview application, and to then get the multiview window to be spawned from a tableview didSelectRowAtIndexPath event in the RootViewController, but I am seeing a warning message telling me that the AppDelegate might not respond to the displayView method, and of course this does not respond.
How do I hook the appDelegate back to the actual delegate?
Alternatively, how would one hand code a TableView into this application?
Thank you in advance for your assistance. |
|
03
Jan 2010
|
Arseniy Banayev This is probably the single most useful article I've found on iPhone dev. The language is clear, the code is even clearer, and it works like a charm. Also, expansion is easy, so this template is wonderful. I suggest making a downloadable Xcode template with heavy comments or something, so the user knows what to change and how to add more views.
Thank you so much! |
|
04
Jan 2010
|
Hardik Hello Sir, Really a nice document. But can you help me with this. I have an application developed in OPENGL ES. I want to use UIVEWCONTROLLER.Can you help me this |
|
14
Jan 2010
|
shubham I wonder if you can have a EAGLview as one of the views. I see Adam above has given an idea, but how about unloading and reloading again and again...
a sample code of the same will be wonderful! |
|
04
Feb 2010
|
Gubb Wow, thanks! This saved my final project from becoming a complete failure. Awesome! |
|
08
Feb 2010
|
Yohannes Woldemariam I learned a lot from this program. Thanks you very much, but how do you include a view with hierarchical information, (tableview and navigation controller)
|
|
08
Feb 2010
|
Yohannes Woldemariam I learned a lot from this program. Thanks you very much, but how do you include a view with hierarchical information, (tableview and navigation controller)
|
Submit a Comment: