280 likes | 439 Views
Nav Controllers. UINavigationController. Overview. Nav Controller basics Like a tabview controller, a navViewController manages views A navigationViewController uses a stack navigationViewControllers are good for hierarchies
E N D
Nav Controllers UINavigationController
Overview • Nav Controller basics • Like a tabview controller, a navViewController manages views • A navigationViewController uses a stack • navigationViewControllers are good for hierarchies • The navigation controller is mostly used on iPhone apps for iPad apps the splitViewControlleris used instead. • Reference • Apple Developer Reference
Overview • Nav Controller basics • When you create a navigationController project, the first view that is displayed is created • Called the masterViewController.h and .m in Xcode • This is the root controller or main controller. • In the Xcodenav controller project one of the subsidaryviews is provided. • It’s called the detailedViewController.h and .m • When a row in the root controller is selected • A corresponding view controller is pushed onto the controller stack • The view associated with the pushed view controller appears
Navigation Stack Initially the masterViewController view is displayed and pushed on the stack MasterViewController
Navigation Stack When a row is pressed, a detail view controller is pushed onto the stack DetailViewControler MasterViewController
Navigation Stack And the detailed view is shown DetailViewControler MasterViewController
Navigation Stack When the return button is pressed, the detailedViewController is popped off the stack. DetailViewControler MasterViewController
Navigation Stack And the top of stack controller view (masterViewController in this case) is displayed. MasterViewController
Nav View • A navigation controller contains a navigation bar and a view by default. The Xcode navigation project has a navigation bar. These buttons are in the default project. The navigation controller has a title The Xcode navigation project uses a table view Navigation Controller Table view cell
Nav View • When a row is selected a detailed view is displayed. The navigation bar title changes A button back to the previous controller is automatically provided. Detailed view
The app • We’ll create a navigation app that uses tables for the view
Creating • Create a new project • Select master-detail application • Choose a name, etc. • Leave unchecked: include unit tests, use storyboards • Make the project for the iPhone • 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 • appDelegate, master and detail view controllers with their nibs.
What did you get? • appDelegate, master and detail view controllers with their nibs. CMPMasterViewController controls the root view that is initially displayed CMPDetailViewController controls the detail view that is displayed when a row is selected. You might need many different ViewControllers if you have many different views for the different rows.
What did you get? • appDelegate, master and detail view controllers with their nibs. CMPMasterViewController nib. Contains a UITableView DetailViewController nib. Contains a label. In Xcode 5 you will see storyboards
The master view (.h) You won’t see this property if you’re using storyboards; Storyboards use segues #import <UIKit/UIKit.h> @class CMPDetailViewController; @interface CMPMasterViewController : UITableViewController @property (strong, nonatomic) CMPDetailViewController *detailViewController; @end Need to store pointers to all of the viewControllers that you can load from the first view. In this example we’ll use the sameviewController for all of the views that we’ll load.
The master view (.m) #import "CMPMasterViewController.h" #import "CMPDetailViewController.h" @interface CMPMasterViewController () { NSMutableArray *_objects; } @end @implementation CMPMasterViewController −(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNilbundle:nibBundleOrNil]; if (self) { self.title = NSLocalizedString(@"Master", @"Master"); } return self; } This is how we create private variables in a class. _objects will hold the data for the rows. This is the same way we initialized a viewController in the tabbed example. This method is not present if storyboards are used
The master view • The masterViewController.m file has these methods: −(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil −(void)viewDidLoad (void)insertNewObject:(id)sender (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath (BOOL)tableView:(UITableView *)tableViewcanEditRowAtIndexPath:(NSIndexPath *)indexPath Used to add buttons to the navigation bar Used to add a table entry to the table view Returns 1 Just creates and returns a table Cell. Uses the instance variable _Objects to hold the data Returns yes. Allows table cells to be edited.
The master view (cont) • The masterViewController.m file has these methods: (void)tableView:(UITableView *)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyleforRowAtIndexPath:(NSIndexPath *)indexPath (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath Either deletes a row entry or adds a new row entry. When cell is selected allocates and initializes the appropriate view controller and pushes it on the navigation stack. Storyboards have the method prepareForSegue instead
The master view (cont) −(void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.leftBarButtonItem = self.editButtonItem; UIBarButtonItem *addButton = [[UIBarButtonItemalloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAddtarget:self action:@selector(insertNewObject:)]; self.navigationItem.rightBarButtonItem = addButton; } Add a left button to the nav bar. The edit button is built in. These two lines add a right button to the nav bar. When clicked, the method (called selector in Objective C) insertNewObject will be called.
The master view (cont) −(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (!self.detailViewController) { self.detailViewController = [[CMPDetailViewControlleralloc] initWithNibName:@"CMPDetailViewController" bundle:nil]; } NSDate*object = _objects[indexPath.row]; self.detailViewController.detailItem = object; [self.navigationControllerpushViewController:self.detailViewControlleranimated:YES]; } Create a new instance of the view controller that we will use for the new view. Get the name for this row from the _objects array Change the value in the new ViewController’s instance variable. Push the new view controller onto the navigation stack Storyboards have the method prepareForSegue instead
The master view (cont) Create a new row entry. −(void)insertNewObject:(id)sender { if (!_objects) { _objects = [[NSMutableArrayalloc] init]; } [_objects insertObject:[NSDate date] atIndex:0]; NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; [self.tableViewinsertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } Add the current date as the data for the new row. Put this into the _Objects array since this array stores our table data. Find the indexPath for the new row. Insert the new row into the table.
The master view (cont) This is how we can edit a row in the viewController −(void)tableView:(UITableView *)tableViewcommitEditingStyle:(UITableViewCellEditingStyle)editingStyleforRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [_objects removeObjectAtIndex:indexPath.row]; [tableViewdeleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. } } This is set if the delete button is clicked Remove the entry from the corresponding row of our _objects array. Delete the row from the table. If we wanted to edit the row, could do it here.
Add a new controller This technique does not work for storyboards. Must add a new controller via the storyboard.storyboard • First add a new controller class: • File->New->File • Choose Cocoa Touch, Objective-C class • Class is CMPSecondViewController • Include a nib • Uncheck “targeted for iPad” • Make sure it’s stored with your files and that the checkbox by “Targets” is checked. • Go to nib, add label and change background color.
CMPMasterViewController.h • Add new property #import <UIKit/UIKit.h> @class CMPDetailViewController; @class CMPSecondViewController; @interface CMPMasterViewController : UITableViewController @property (strong, nonatomic) CMPDetailViewController *detailViewController; @property (strong, nonatomic) CMPSecondViewController*secondViewController; @end This variable will hold an instance of the second view controller.
CMPMasterViewController.m • Recognize the first row (row 0) as different view controller −(void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath { if ([indexPath row] == 0) { if (!self.secondViewController) { self.secondViewController = [[CMPSecondViewControlleralloc] initWithNibName:@"CMPSecondViewController" bundle:nil]; } [self.navigationControllerpushViewController:self.secondViewControlleranimated:YES]; } Recognize the first row so that we can use a different view. Push this view controller onto the navigator stack. This method continued on next slide
CMPMasterViewController.m • Recognize the first row (row 0) as different view controller else{ if (!self.detailViewController) { self.detailViewController = [[CMPDetailViewControlleralloc] initWithNibName:@"CMPDetailViewController" bundle:nil]; } NSDate *object = _objects[indexPath.row]; self.detailViewController.detailItem = object; [self.navigationControllerpushViewController:self.detailViewControlleranimated:YES]; } // end of else } // end of method Everything inside the else is the old code from the method. It loads a detail view.
Other modifications to cells • See Beginning iOS 6 Development chapter 9 • Disclosure buttons • Checklist view • Tappable button in row • Movable rows • Deletable rows • Editable rows