330 likes | 474 Views
Multiple Views. UINavigationController. Controller Architecture. Root controller Controls the first view that the user sees The view controller class (and xib ) that manages which view is currently being shown to the user E.g., a navigation controller maintains a hierarchy of views
E N D
Multiple Views UINavigationController
Controller Architecture • Root controller • Controls the first view that the user sees • The view controller class (and xib) that manages which view is currently being shown to the user • E.g., a navigation controller maintains a hierarchy of views • A tab controller switches views based on which tab button is selected. • Other controllers • Every view in the application has it’s own viewController and own xib file • Taps in the content area go to the viewController • Taps in the navigation area (e.g., the tabs) go to the root controller.
The app • We will create a navigation view from scratch • Start with no views • This is even simplier than the single view app • Not the normal way; but we learn how to build
Creating • Create a new project • Select empty application • Choose a name, etc. • Leave unchecked: use core data, include unit tests • Check use automatic reference counting • Choose a place to save • Do not need to use git
What did you get? • Look at the file navigator • Only two files: the appDelegate.h and .m • Not even a xib!
Creating the root controller • Need some controllers: • Create new file • Choose Cocoa Touch, then Objective-C class • Click next • In the Subclass of field choose UIViewController • in the Class field, type CMPSwitchViewController (where CMP is the prefix you chose when you created the project) • Uncheck Targeted for iPad • Uncheck With XIB for user interface We’ll create our own xib later. • Click next • The directory chooser dialog should have picked the parent of the correct folder to store this in. choose the folder where you see the appDelegate.m and .h files. • Also make sure that the group is switchViewsand that the Target checkbox is checked! If it isn’t, your new file will not be compiled!
Creating other controllers • You should see two new files (the .h and .m) in the Project Navigator in the group with the appDelegate files. • Now follow the same steps to create two controllers: • CMPBlueViewController.m (and the .h) • CMPYellowViewController.m (and the .h)
Creating nibs • FileNewFile • Choose User Interface in the list on the left • Click on the icon for the View template • Click next, choose iPhone • Choose the name SwitchView Make sure that the directory, group, and target are correct. • Follow the same process to create the BlueView.xib and the YellowVew.xibfiles.
Hooking up the appDelegate • Go to CMPAppDelegate.h, add the bold code (p. 152 of book) #import <UIKit/UIKit.h> @class CMPSwitchViewController; @interface CMPAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) CMPSwitchViewController *switchViewController; @end This makes the class known without actually importing This will be a pointer to our root viewController
Hooking up the appDelegate Go to CMPAppDelegate.m, add the bold code (p. 153 of book) #import "CMPAppDelegate.h" #import "CMPSwitchViewController.h" @implementation CMPAppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindowalloc] initWithFrame:[[UIScreenmainScreen] bounds]]; // Override point for customization after application launch. self.switchViewController = [[CMPSwitchViewControlleralloc] initWithNibName:@"SwitchView" bundle:nil]; UIView *switchView = self.switchViewController.view; CGRectswitchViewFrame = switchView.frame; switchViewFrame.origin.y += [UIApplicationsharedApplication].statusBarFrame.size.height; switchView.frame = switchViewFrame; self.window.rootViewController = self.switchViewController; self.window.backgroundColor = [UIColorwhiteColor]; [self.windowmakeKeyAndVisible]; return YES; } Include the header file Create an instance of the root controller (and load its xib) Change the size of the view so that it’s not hidden by the status bar. If we create a view app this is done for us. Add view to window
Set up the root controller • Go to CMPSwitchViewController.h • Add outlets and actions • Need one action method to switch views • Need pointers for the two view controllers for these views (they don’t need to be outlets; the view controllers are code not components) • See next slide for the .h file
Set up the root controller #import <UIKit/UIKit.h> @class CMPBlueViewController; @class CMPYellowViewController; @interface CMPSwitchViewController : UIViewController @property (strong, nonatomic) CMPBlueViewController *blueViewController; @property (strong, nonatomic) CMPYellowViewController *yellowViewController; −(IBAction)switchViews:(id)sender; @end Need to know about these, but not modify them These point to the code view controllers (not the IB views) This IBAction will be called to switch views
Fixing the main xib • Go to SwitchView.xib • There are 3 icons in the dock: File’s owner, First Responder, and View. • by default, the File’s owner is an NSObject. • Single-click the File’s owner icon, go to the identity inspector (third icon) • Change the NSObjectto CMPSwitchViewController
SwitchView.xib • Now go to the connections inspector (last icon) • Under received actions you should see the switchViewsaction that we created earlier. • If you don’t see this, there is a mistake!
SwitchView.xib • Now grab a toolbarView and put on the bottom of the view.
If you ever need more buttons, drag Bar Button Items from the library to the tool bar. SwitchView.xib • Change the name of the button to switch views • Toolbar buttons only support a single action (like a touch-up inside) • Select the button; it’s tricky to do this; can use the dock • To tell if you selected the button: identity inspector should say the class is UIBarButtonItem or the attributes inspector should say Bar Button Item • Control drag from button to File’s Owner and select the switchViewsmethod • or go to the connections inspector and drag from the button in the Sent Actions section to the File’s Owner
SwitchView.xib • Now connect the view property to the view in the nib • If we had created a single view project this would have been done automagically. • Since we started with a NSObject, there was initially no view property. • We changed the file’s owner to a viewController, but now must connect the view in the xib to the view property. • Control-drag from the File’s Owner to the view in the dock. • Choose the view property from the resulting pop-up
SwitchView.xib Control-drag from File’s Owner to View Choose view from the pop-up box. Or click on View and then go to connections inspector and drag from the circle in the referencing outlet to the File’s Owner
View Controller • Go to CMPSwitchViewcontroller.m • Add references to the other two view controllers #import "CMPSwitchViewController.h” #import "CMPBlueViewController.h” #import "CMPYellowViewController.h"
View Controller • Change the viewDidLoad method to initialize a view −(void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.blueViewController = [[BIDBlueViewControlleralloc]initWithNibName:@"BlueView" bundle:nil]; [self.viewinsertSubview:self.blueViewController.view atIndex:0]; } Create an instance of the blue view controller; indicate the name of its nib Don’t use the “.xib” extension! We make the Blue View a subviewof our own view; it will be at the back of all the other subviews in our view (that’s what the 0 means). We want it below the toolbar Keep a pointer to the Blue View Controller in a property
View Controller • Where’s the yellowViewController? • Don’t create it initially; the user may never click on the switchViewsbutton, so why waste the memory? • Instead, create it in the IBAction method switchViews:(id) sender • switchViews • First check whether yellowViewcontroller’ssuperview is nil • If it is nil, then the blue view is attached to the superview (which is the view of the Root ViewController, e.g., CMPSwitchViewController • Since the user wants to switch views, this means that we must detach the blue view and attach the yellow view. • If the superview is not nil, then the yellow view is attached • So detach the yellow view and attach the blue view
View Controller if the yellow view has no superview, will need to unload blue view and load yellow view −(IBAction)switchViews:(id)sender { if (self.yellowViewController.view.superview == nil) { if (self.yellowViewController == nil) { self.yellowViewController = [[CMPYellowViewControlleralloc] initWithNibName:@"YellowView" bundle:nil]; [self.blueViewController.viewremoveFromSuperview]; [self.viewinsertSubview:self.yellowViewController.view atIndex:0]; } else { // see next slide } } if there is no yellow view allocate it Remove the blue view, add the yellow view
View Controller −(IBAction)switchViews:(id)sender { if (self.yellowViewController.view.superview == nil) { // on previous slide } else { if (self.blueViewController == nil) { self.blueViewController = [[CMPBlueViewControlleralloc] initWithNibName:@"BlueView" bundle:nil]; } [self.yellowViewController.viewremoveFromSuperview]; [self.viewinsertSubview:self.blueViewController.view atIndex:0]; } } if there is no blue view allocate it (may have been flushed from memory) Remove the yellow view, add the blue view
View Controller −(void)didReceiveMemoryWarning{ [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. if (self.blueViewController.view.superview == nil) { self.blueViewController = nil; } else { self.yellowViewController = nil; } } Be a good memory citizen & release view that is not being used
Content Views • We haven’t created the content views yet! • First need some IBAction methods • In CMPBlueViewController.h: #import <UIKit/UIKit.h> @interface CMPBlueViewController : UIViewController −(IBAction)blueButtonPressed; @end • In CMPYellowViewController.hput −(IBAction)YellowButtonPressed;
Content Views • Click on BlueView.xib • Click on File’s Owner in the dock • Click on identity inspector and change class to CMPBlueViewController • Click on View in the dock • Click on attributes inspector and change background color to blue.
Content Views • Must make the blue view fit within the root controller’s view • Click on attributes inspector • In the first section (simulated metrics) change status bar to none and Bottom Bar to Toolbar • IB changes the view size automagically
Content Views • Drag a button onto the screen • Change name to Press Me • Connect to File’s OwnerIBActionblueButtonPressed • Final action • Connect the File’s OwnerIBOutlet property view to our view icon.
Content Views • Repeat with Yellow View
Content Viewsmaking a transition Set up the animation: must create an animation block with beginAnimations:context: −(IBAction)switchViews:(id)sender { [UIViewbeginAnimations:@"View Flip" context:nil]; [UIView setAnimationDuration:1.25]; [UIViewsetAnimationCurve:UIViewAnimationCurveEaseInOut]; if (self.yellowViewController.view.superview == nil) { if (self.yellowViewController == nil) { self.yellowViewController = [[CMPYellowViewControlleralloc] initWithNibName:@"YellowView” bundle:nil]; } [UIViewsetAnimationTransition: UIViewAnimationTransitionFlipFromRightforView:self.viewcache:YES]; [self.blueViewController.viewremoveFromSuperview]; [self.viewinsertSubview:self.yellowViewController.view atIndex:0]; } Set the animation duration EaseInOut: start slow, speed, slow again; more natural This is one command: set type of transition
Content Viewsmaking a transition else { if (self.blueViewController == nil) { self.blueViewController = [[CMPBlueViewControlleralloc] initWithNibName:@"BlueView” bundle:nil]; } [UIViewsetAnimationTransition: UIViewAnimationTransitionFlipFromLeftforView:self.viewcache:YES]; [self.yellowViewController.viewremoveFromSuperview]; [self.viewinsertSubview:self.blueViewController.view atIndex:0]; } [UIViewcommitAnimations]; } Set different type of transition Cache option speeds up animation by capturing beginning image and reusing rather than constantly redrawing Commit the animation so that it plays
Blue and Yellow View controllers • Add the following code to the blueButtonPressedmethod in the blueViewController: - (IBAction)blueButtonPressed { UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Blue View Button Pressed" message:@"You pressed the button on the blue view" delegate:nil cancelButtonTitle:@"Yep, I did." otherButtonTitles:nil]; [alert show]; }
Blue and Yellow View controllers • Add the following code to the blueButtonPressedmethod in the yellowViewController: - (IBAction)yellowButtonPressed { UIAlertView *alert = [[UIAlertViewalloc] initWithTitle:@"Yellow View Button Pressed" message:@"You pressed the button on the yellow view" delegate:nil cancelButtonTitle:@"Yep, I did." otherButtonTitles:nil]; [alert show]; }