View Controllers
Why Model-View-Controller? Ever used the word spaghetti to describe code? Clear responsibilities make things easier to maintain Avoid having one monster class that does everything
Why Model-View-Controller? Separating responsibilities also leads to reusability By minimizing dependencies, you can take a model or view class you ve already written and use it elsewhere Think of ways to write less code
Communication and MVC How should objects communicate? Which objects know about one another? Model Example: Polygon class Not aware of views or controllers Typically the most reusable Communicate generically using... Key-value observing Notifications
Communication and MVC How should objects communicate? Which objects know about one another? View Example: PolygonView class Not aware of controllers, may be aware of relevant model objects Also tends to be reusable Communicate with controller using... Target-action Delegation
Communication and MVC How should objects communicate? Which objects know about one another? Controller Knows about model and view objects The brains of the operation Manages relationships and data flow Typically app-specific, so rarely reusable
Communication and MVC
View Controllers
Problem: Managing a Screenful Controller manages views, data and application logic Apps are made up of many of these Would be nice to have a well-defined starting point A UIView for views Common language for talking about controllers
Problem: Building Typical Apps Some application flows are very common Navigation-based Tab bar-based Combine the two Don t reinvent the wheel Plug individual screens together to build an app
View Controllers Many of the standard interface behaviors in ios applications; Default behaviors that you can use as is or customize when needed. A convenient way to organize your application s user interface and content.
Organizing Contents in Recipe Management
Patterns for Organizing Content Navigation Bar Tab Bar
Navigation Bar Hierarchy of content Drill down into greater detail
Tab Bar Self-contained modes
Parts of a Screenful
UIViewController Basic building block Manages a screenful of content Subclass to add your application logic
View Controllers In UIKit
Custom View Controllers Create your own UIViewController subclass for each screen Plug them together using existing composite view controllers Every Apps has at least one May interact with other controller objects
Anatomy of View Controller
Key Tasks Customizing View Controller You must configure the view to be loaded by your view controller; You must decide which orientations your view controller supports; You must clean up the memory that is managed by your view controller;
Subclassing UIViewController Member variables pointing to the objects containing the data to be displayed by the corresponding views Member variables (or outlets) pointing to key view objects with which your view controller must interact Action methods that perform tasks associated with buttons and other controls in the view hierarchy Any additional methods needed to implement your view controller s custom behavior
Your View Controller Subclass #import <UIKit/UIKit.h> @interface MyViewController : UIViewController { // A view controller will usually // manage views and data NSMutableArray *mydata; UILabel *mylabel; } // Expose some of its contents to clients @property (readonly) NSArray *mydata; // And respond to actions - (void)dosomeaction:(id)sender;
View Management Cycle (Load)
Unload View from Memory
Creating the View for Your View Controller The main job of a view controller is to load and unload its view as needed. Most view controllers load their views from an associated nib file. MyViewController* vc = [[[MyViewController alloc] initwithnibname:@"myviewcontroller" bundle:nil] autorelease];
Load View from Nib File
@interface MyViewController : UIViewController { } id mybutton; id mytextfield; @property (nonatomic) IBOutlet id mybutton; @property (nonatomic) IBOutlet id mytextfield; - (IBAction)myAction:(id)sender;
Creating views programmatically - (void)loadview { self.wantsfullscreenlayout = YES; MetronomeView *view = [[MetronomeView alloc] @initwithframe:[uiscreen mainscreen].applicationframe]; view.metronomeviewcontroller = self; self.view = view; self.metronomeview = view; [view release]; }
Presenting a View Controller s View Display the view directly by adding it to a window using the addsubview: method. - (void)applicationdidfinishlaunching:(uiapplication *)application { // At this point, the main nib file is loaded. // It is a good idea to set the view's frame before adding it to a window. [viewcontroller.view setframe:[[uiscreen mainscreen] applicationframe]]; } [window addsubview:viewcontroller.view]; [window makekeyandvisible];
Managing Memory Efficiently Allocating critical data structures required by your view controller Creating your view objects Allocating or loading data to be displayed in your view Releasing references to view objects Releasing data that is not needed when your view is not displayed Responding to low-memory notifications Releasing critical data structures required by your view controller Initialization methods loadview viewdidload viewdidunload dealloc viewdidunload didreceivememorywa rning dealloc
Managing a View Controller s Interface Orientation Override your view controller s shouldautorotatetointerfaceorientation: method and declare the orientations it supports; Configure the autoresizing mask for each view in your view controller s view hierarchy;
Processing a one-step interface rotation
Implementing shouldautorotatetointerfaceorientation: - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) orientation{ if ((orientation == UIInterfaceOrientationPortrait) (orientation == UIInterfaceOrientationLandscapeLeft)) } return YES; return NO; Four Defined Orientations: UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
Presenting the landscape view controller @implementation PortraitViewController - (id)init { self = [super initwithnibname:@"portraitview" bundle:nil]; if (self) { isshowinglandscapeview = NO; self.landscapeviewcontroller = [[[LandscapeViewController alloc] initwithnibname:@"landscapeview" bundle:nil] autorelease]; [[UIDevice currentdevice] begingeneratingdeviceorientationnotifications]; [[NSNotificationCenter defaultcenter] addobserver:self selector:@selector(orientationchanged: name:uideviceorientationdidchangenotification object:nil]; } return self; }
- (void)orientationchanged:(nsnotification *)notification { UIDeviceOrientation deviceorientation = [UIDevice currentdevice].orientation; } if (UIDeviceOrientationIsLandscape(deviceOrientation) &&!isshowinglandscapeview) { [self presentmodalviewcontroller:self.landscapeviewcontroller animated:yes]; isshowinglandscapeview = YES; } else if (UIDeviceOrientationIsPortrait(deviceOrientation) && isshowinglandscapeview) { [self dismissmodalviewcontrolleranimated:yes]; isshowinglandscapeview = NO; }
Responding to Orientation Changes in Two Steps