pushplay

interactive · design · studio


< Back to Main

Framework for having Multiple Views in an iPhone app

May 6, 2009
|

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.

flowchart representing a parent app controller and view controller with multiple subviews

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"
// you have to import the header files for
// any views that this parent controls
#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 {
       // display Welcome screen
       currentView = [[View01 alloc] init];
       [self.view addSubview:currentView.view];
 
   [super viewDidLoad];
}
 
- (void)didReceiveMemoryWarning {
   [super didReceiveMemoryWarning]; // Releases the view if it
doesn't have a superview
   // Release anything that's not essential, such as cached data
}
 
 
- (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]; // Releases the view if it
doesn't have a superview
   // Release anything that's not essential, such as cached data
}
 
 
- (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]; // Releases the view if it
doesn't have a superview
   // Release anything that's not essential, such as cached data
}
 
 
- (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!

38 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)


12 Feb
2010
Alberto Juarez
Hey Adam THANKS for your post, I'd been searching for the code to link my UIViewController to a EAGLView and your tip totally worked for me! Do you how can I swich views back and forth?
16 Feb
2010
Brian
Hi, thanks for the great tutorial, I was just wondering if instead of using an int to switch between view controllers if you could allocate a new view controller and set it to autorelease, pass it to displayView, and switch between views like that. Then perhaps you could also pass a UIViewAnimationTransition enum like UIViewAnimationTransitionFlipFromLeft and handle transitions aswell.
17 Feb
2010
radha
hi !!! m a beginner n i learnt a lot from u r tutorial. Thank you.
13 Apr
2010
watt
Thankes a lot! I also learn what I'm researching for in comments. It's a lucky day
20 Apr
2010
ROHITH
I have seen your blog in the iPhone devSDK website and I followed your tutors ..which really help me a lot ......!!!! I want to develop Multiple View with Navigation Based application .

Kindly , please provide a tutor for Multiple Views using Navigation Based Application.

What I mean is suppose if we take 4 Views.(Moving from 1 to 2 to 3 to 4 and VICE VERSA ,using PREVIOUS and FORWARD BUTTON within these views ).
In 1st View,data will be row(Ex: DEll
HP
SONY
LENOVA) and when we click any ROW CONTENT, it must go to 2nd view(which contain some TEXTS, with 2 paragraph with some spacing between 2 paragraphs) .

And in the same way from 2nd View to 3rd view ( when we click ,here also TEXT will be displayed and button like PREVIOUS and FORWARD BUTTON ).

Generally ,It would be better if we display TEXT in LANDSCAPE MODE .


I will be very thankful if u provide a tutor on it......



WITH A WORD OF THANKS,
ROHITH

20 Apr
2010
ROHITH
I have seen your blog in the iPhone devSDK website and I followed your tutors ..which really help me a lot ......!!!! I want to develop Multiple View with Navigation Based application .

Kindly , please provide a tutor for Multiple Views using Navigation Based Application.

What I mean is suppose if we take 4 Views.(Moving from 1 to 2 to 3 to 4 and VICE VERSA ,using PREVIOUS and FORWARD BUTTON within these views ).
In 1st View,data will be row(Ex: DEll
HP
SONY
LENOVA) and when we click any ROW CONTENT, it must go to 2nd view(which contain some TEXTS, with 2 paragraph with some spacing between 2 paragraphs) .

And in the same way from 2nd View to 3rd view ( when we click ,here also TEXT will be displayed and button like PREVIOUS and FORWARD BUTTON ).

Generally ,It would be better if we display TEXT in LANDSCAPE MODE .


I will be very thankful if u provide a tutor on it......



WITH A WORD OF THANKS,
ROHITH

20 Apr
2010
ROHITH
I have seen your blog in the iPhone devSDK website and I followed your tutors ..which really help me a lot ......!!!! I want to develop Multiple View with Navigation Based application .

Kindly , please provide a tutor for Multiple Views using Navigation Based Application.

What I mean is suppose if we take 4 Views.(Moving from 1 to 2 to 3 to 4 and VICE VERSA ,using PREVIOUS and FORWARD BUTTON within these views ).
In 1st View,data will be row(Ex: DEll
HP
SONY
LENOVA) and when we click any ROW CONTENT, it must go to 2nd view(which contain some TEXTS, with 2 paragraph with some spacing between 2 paragraphs) .

And in the same way from 2nd View to 3rd view ( when we click ,here also TEXT will be displayed and button like PREVIOUS and FORWARD BUTTON ).

Generally ,It would be better if we display TEXT in LANDSCAPE MODE .


I will be very thankful if u provide a tutor on it......



WITH A WORD OF THANKS,
ROHITH

23 Apr
2010
Paul
First off great tutorial.

If I implement this code and force the view to landscape I run into an issue. I place a button at (50,50,320,whatever)lets just say on the main page (first one that loads).
The button should only be visable and usable from that page and that works. The issue is that the button is invisible and usable on all other views(which it should not be visable or useable on any other view on the app). If I place the button at (50,50,20,whatever) This problem does not happen.
23 Apr
2010
Paul
First off great tutorial.

If I implement this code and force the view to landscape I run into an issue. I place a button at (50,50,320,whatever)lets just say on the main page (first one that loads).
The button should only be visable and usable from that page and that works. The issue is that the button is invisible and usable on all other views(which it should not be visable or useable on any other view on the app). If I place the button at (50,50,20,whatever) This problem does not happen.
23 Apr
2010
Paul
First off great tutorial.

If I implement this code and force the view to landscape I run into an issue. I place a button at (50,50,320,whatever)lets just say on the main page (first one that loads).
The button should only be visable and usable from that page and that works. The issue is that the button is invisible and usable on all other views(which it should not be visable or useable on any other view on the app). If I place the button at (50,50,20,whatever) This problem does not happen.
23 Apr
2010
Paul
First off great tutorial.

If I implement this code and force the view to landscape I run into an issue. I place a button at (50,50,320,whatever)lets just say on the main page (first one that loads).
The button should only be visable and usable from that page and that works. The issue is that the button is invisible and usable on all other views(which it should not be visable or useable on any other view on the app). If I place the button at (50,50,20,whatever) This problem does not happen.
31 May
2010
Vince
Thanks for this.

Coming from low level programming, I find it magical that the child view is able to destroy itself by telling the super view to release it.

I just started Iphone app development and was wondering how I would go about implementing multiple views. I thought of the same idea as you have but reasoned that if the superview destroyed the child view, when the function call returned to the child view, it would somehow segfault. I guess not!
09 Jun
2010
Bivins
Great tutorial!!! As a newbiee I really liked this and got a lot from it.
I will like to ask a question, I wish to develop an app that has a mixture of views for example the first page or welcome page having an image view, the second a text view and the third might be another image view the fourth just a plain view and I want to navigate from one page to the other by using page transformations that mimicks real page opening...please can anyone help me with ideas on how to go about this?
Thanks a lot.
29 Jul
2010
Einar
Thank you for a great tut.
This is the kind of stuff that I like. Clean, works and my favourite: NO Interface Builder !!
I think IB just messes things up
29 Aug
2010
Masashi
Hi,

I have just read "Framework for having Multiple Views in an iPhone app", and I found it an exact way to do with multiple view.

I like it because I can add views easily working with group / by myself.

Now, I have a question regarding to memory management.

The sample code seems to work kinda like this.
*mem. # is just an example.

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : stays at 1.20MB
4) switch to view two : stays at 1.20MB
5) back to view one : stays at 1.20MB

My question is...
How could I get a result like below using your idea?

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : decrease to 1.00MB
4) switch to view two : increase to 1.20MB
5) back to view one : decrease 1.00MB

I really like your idea, and I want to get more based on it.

I am desperate to know!
29 Aug
2010
Masashi
Hi,

I have just read "Framework for having Multiple Views in an iPhone app", and I found it an exact way to do with multiple view.

I like it because I can add views easily working with group / by myself.

Now, I have a question regarding to memory management.

The sample code seems to work kinda like this.
*mem. # is just an example.

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : stays at 1.20MB
4) switch to view two : stays at 1.20MB
5) back to view one : stays at 1.20MB

My question is...
How could I get a result like below using your idea?

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : decrease to 1.00MB
4) switch to view two : increase to 1.20MB
5) back to view one : decrease 1.00MB

I really like your idea, and I want to get more based on it.

I am desperate to know!
29 Aug
2010
Masashi
Hi,

I have just read "Framework for having Multiple Views in an iPhone app", and I found it an exact way to do with multiple view.

I like it because I can add views easily working with group / by myself.

Now, I have a question regarding to memory management.

The sample code seems to work kinda like this.
*mem. # is just an example.

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : stays at 1.20MB
4) switch to view two : stays at 1.20MB
5) back to view one : stays at 1.20MB

My question is...
How could I get a result like below using your idea?

1) initialize with view one : Allocated Mem. 1.00 MB
2) switch to view two : increase to 1.20MB
3) back to view one : decrease to 1.00MB
4) switch to view two : increase to 1.20MB
5) back to view one : decrease 1.00MB

I really like your idea, and I want to get more based on it.

I am desperate to know!

Submit a Comment:

Your Name:
Email Address:
Comments:
Enter what you see: Verification Image