Upload
sivakumar7
View
7
Download
0
Embed Size (px)
DESCRIPTION
08_NavigationTabBarController
Citation preview
Naviga&on and Tab Bar Controllers and Table View
UINaviga)onController
• Stack of view controllers • Naviga)on bar
How It Fits Together
• Top view controller’s view • Top view controller’s )tle • Previous view controller’s )tle • Top view controller’s toolbar items (iPhone OS 3.0)
The views of a naviga)on interface
Objects managed by the naviga)on controller
The naviga)on stack
Loading Your Naviga&on Interface from a Nib File
Crea)ng a Naviga)on Controller Programma)cally
-‐ (void)applica)onDidFinishLaunching:(UIApplica)on *)applica)on{ UIViewController *rootController = [[MyRootViewController alloc] init]; naviga)onController = [[UINaviga)onController alloc] initWithRootViewController:rootController]; [rootController release]; window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; [window addSubview:naviga)onController.view]; [window makeKeyAndVisible];}
Modifying the Naviga)on Stack • Push to add a view controller -‐ (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
• Pop to remove a view controller -‐ (UIViewController *)popViewControllerAnimated:(BOOL)animated;
• Set to change the en&re stack of view controllers • (iPhone OS 3.0) -‐ (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated;
Pushing Your First View Controller -‐ (void)applica)onDidFinishLaunching { // Create a naviga)on controller navController = [[UINaviga)onController alloc] init]; // Push the first view controller on the stack [navController pushViewController:firstViewController animated:NO];
// Add the naviga)on controller’s view to the window [window addSubview:navController.view]; }
In Response to User Ac)ons • Push from within a view controller on the stack -‐ (void)someAc)on:(id)sender { // Poten)ally create another view controller UIViewController *viewController = ...;
[self.naviga)onController pushViewController:viewController animated:YES];
} • Almost never call pop directly!
– Automa)cally invoked by the back bu_on
Messages sent during stack changes
A Controller for Each Screen
Connec)ng View Controllers
• Mul)ple view controllers may need to share data
• One may need to know about what another is doing – Watch for added, removed or edited data – Other interes)ng events
How Not To Share Data • Global variables or singletons
– This includes your applica&on delegate! • Direct dependencies make your code less reusable
– And more difficult to debug & test
Best Prac)ces for Data Flow • Figure out exactly what needs to be communicated • Define input parameters for your view controller • For communica)ng back up the hierarchy, use loose coupling – Define a generic interface for observers (like delega)on)
Customizing Naviga)on
• Bu_ons or custom controls • Interact with the en)re screen
Naviga)on bar styles
The objects associated with a naviga)on bar
UINaviga)onItem
• Describes appearance of the naviga)on bar – Title string or custom )tle view – Lee & right bar bu_ons – More proper)es defined in UINaviga)onBar.h
• Every view controller has a naviga&on item for customizing – Displayed when view controller is on top of the stack
Naviga)on Item Ownership
The objects associated with a naviga)on bar
Displaying a Title
• UIViewController already has a )tle property – @property(nonatomic,copy) NSString *)tle;
• Naviga)on item inherits automa)cally – Previous view controller’s )tle is displayed in back bu_on
viewController.)tle = @“Detail”;
Lee & Right Bu_ons
• UIBarBu_onItem – Special object, defines appearance & behavior for items in naviga)on bars and toolbars
• Display a string, image or predefined system item
• Target + ac)on (like a regular bu_on)
Text Bar Bu_on Item -‐ (void)viewDidLoad { UIBarBu_onItem *fooBu_on = [[UIBarBu_onItem alloc] initWithTitle:@"Foo” style:UIBarBu_onItemStyleBordered target:self ac)on:@selector(foo:)];
self.naviga)onItem.leeBarBu_onItem = fooBu_on;
[fooBu_on release];
}
System Bar Bu_on Item -‐ (void)viewDidLoad { UIBarBu_onItem *addBu_on = [[UIBarBu_onItem alloc] initWithBarBu_onSystemItem:UIBarBu_onSystemItemAdd style:UIBarBu_onItemStyleBordered target:self ac)on:@selector(add:)];
self.naviga)onItem.rightBarBu_onItem = addBu_on; [addBu_on release]; }
Edit/Done Bu_on • Very common pa_ern • Every view controller has one available
– Target/ac)on already set up
self.naviga)onItem.leeBarBu_onItem = self.editBu_onItem; // Called when the user toggles the edit/done bu_on -‐ (void)setEdi)ng:(BOOL)edi)ng animated:(BOOL)animated { // Update appearance of views
}
Custom Title View • Arbitrary view in place of the )tle
UISegmentedControl *segmentedControl = ... self.naviga)onItem.)tleView = segmentedControl; [segmentedControl release];
Back Bu_on • Some)mes a shorter back bu_on is needed
self.)tle = @“Hello there, CS193P!”; UIBarBu_onItem *heyBu_on = [[UIBarBu_onItem alloc] initWithTitle:@“Hey!” ...];
self.naviga)onItem.backBu_onItem = heyBu_on; [heyBu_on release];
// View 3 -‐ Custom right bar bu_on with a view UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems: [NSArray arrayWithObjects: [UIImage imageNamed:@"up.png"], [UIImage imageNamed:@"down.png"], nil]]; [segmentedControl addTarget:self ac)on:@selector(segmentAc)on:) forControlEvents:UIControlEventValueChanged]; segmentedControl.frame = CGRectMake(0, 0, 90, kCustomBu_onHeight); segmentedControl.segmentedControlStyle = UISegmentedControlStyleBar;segmentedControl.momentary = YES; defaultTintColor = [segmentedControl.)ntColor retain]; // keep track of this for later UIBarBu_onItem *segmentBarItem = [[UIBarBu_onItem alloc] initWithCustomView:segmentedControl]; [segmentedControl release]; self.naviga)onItem.rightBarBu_onItem = segmentBarItem; [segmentBarItem release];
Toolbar items in a naviga)on interface
(void)configureToolbarItems { UIBarBu_onItem *flexibleSpaceBu_onItem = [[UIBarBu_onItem alloc] initWithBarBu_onSystemItem:UIBarBu_onSystem ItemFlexibleSpace target:nil ac)on:nil]; // Create and configure the segmented control UISegmentedControl *sortToggle = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Ascending”, @"Descending", nil]]; sortToggle.segmentedControlStyle = UISegmentedControlStyleBar; sortToggle.selectedSegmentIndex = 0; [sortToggle addTarget:self ac)on:@selector(toggleSor)ng:) forControlEvents:UIControlEventValueChanged];
// Create the bar button item for the segmented control UIBarButtonItem *sortToggleButtonItem = [[UIBarButtonItem alloc] initWithCustomView:sortToggle]; [sortToggle release]; // Set our toolbar items self.toolbarItems = [NSArray arrayWithObjects: flexibleSpaceButtonItem, sortToggleButtonItem, flexibleSpaceButtonItem, nil]; [sortToggleButtonItem release]; [flexibleSpaceButtonItem release]; }
UITabBarController
• Array of view controllers • Tab bar
How It Fits Together
• Selected view controller’s view • All view controllers’ )tles
The views of a tab bar interface
A tab bar controller and its associated view controllers
Tab bar items of the iPod applica)on
Nib file containing a tab bar interface
Seong Up a Tab Bar Controller�-‐ (void)applica)onDidFinishLaunching // Create a tab bar controller tabBarController = [[UITabBarController alloc] init];
// Set the array of view controllers tabBarController.viewControllers = myViewControllers;
// Add the tab bar controller’s view to the window [window addSubview:tabBarController.view];
}
Tab Bar Appearance
• View controllers can define their appearance in the tab bar
• UITabBarItem – Title + image or system item
• Each view controller comes with a tab bar item for customizing
Crea)ng Tab Bar Items • Title and image
-‐ (void)viewDidLoad {
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:@“Playlists” image:[UIImage imageNamed:@“music.png”] tag:0]; self.tabBarItem = item; [item release];
}
Crea)ng Tab Bar Items • System item
-‐ (void)viewDidLoad { UITabBarItem *item = [[UITabBarItem alloc] initWithTabBarSystemItem: UITabBarSystemItemBookmarks tag:0] self.tabBarItem = item; [item release];
}
Crea)ng the view controller’s tab bar item
-‐ (id)init { if (self = [super initWithNibName:@"MyViewController" bundle:nil]) { self.)tle = @"My View Controller”; UIImage* anImage = [UIImage imageNamed:@"MyViewControllerImage.png"]; UITabBarItem* theItem = [[UITabBarItem alloc] initWithTitle:@"Home" image:anImage tag:0]; self.tabBarItem = theItem; [theItem release]; } return self; }
Removing the current tab -‐ (IBAc)on)processUserInforma)on:(id)sender{
// Call some app-‐specific method to validate the user data. // If the custom method returns YES, remove the tab. if ([self userDataIsValid]) { NSMutableArray* newArray = [NSMutableArray arrayWithArray:self.tabBarController.viewControllers]; [newArray removeObject:self]; [self.tabBarController setViewControllers:newArray animated:YES]; }
}
Preven)ng the selec)on of tabs
- (BOOL)tabBarController:(UITabBarController *)aTabBar shouldSelectViewController:(UIViewController *)viewController { if (![self hasValidLogin] && (viewController != [aTabBar.viewControllers objectAtIndex:0]) ) { // Disable all but the first tab. return NO; } return YES; }
More View Controllers
Tab Bar + Naviga)on Controllers Mul)ple parallel hierarchies
Tab Bar + Naviga)on Controllers
Nes)ng Naviga)on Controllers • Create a tab bar controller
tabBarController = [[UITabBarController alloc] init];
• Create each naviga)on controller navController = [[UINaviga)onController alloc] init]; [navController pushViewController:firstViewController animated:NO];
• Add them to the tab bar controller tabBarController.viewControllers = [NSArray arrayWithObjects: navController, anotherNavController, someViewController, nil];
Table Views
• Display lists of content – Single column, mul)ple rows – Ver)cal scrolling – Large data sets
• Powerful and ubiquitous in iPhone applica)ons
Table View Styles UITableViewStylePlain UITableViewStyleGrouped
Table View Anatomy Plain Style
Table Header
Section
Table Footer
Section Header
Table Cell
Section Footer
Table View Anatomy Grouped Style
Table Header
Section
Table Footer
Section Header
Table Cell
Section Footer
Header and footer of a sec)on
UITabelView
• Declaring methods that allow you to configure the appearance of the table view – specifying the default height of rows or providing a view used as the header for the table
– access to the currently selected row as well as specific rows or cells
– manage selec)ons, scroll the table view, and insert or delete rows and sec)ons.
• UITableView inherits from UIScrollView, which defines scrolling behavior for views with content larger than the size of the window. – UITableView redefines the scrolling behavior to allow ver)cal scrolling only.
Using Table Views
• Displaying your data in the table view • Customizing appearance & behavior
Displaying Data in a Table View
A Naïve Solution
• Table views display a list of data, so use an array [myTableView setList:myListOfStuff];
• Issues with this approach
– All data is loaded upfront – All data stays in memory
A More Flexible Solution
• Another object provides data to the table view – Not all at once – Just as it’s needed for display
• Like a delegate, but purely data-oriented
Calling sequence for crea)ng and configuring a table view
UITableViewDataSource • Provide number of sections and rows
// Optional method, defaults to 1 if not implemented - (NSInteger)numberOfSectionsInTableView:(UITableView *)table;
// Required method - (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section;
• Provide cells for table view as needed
// Required method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
Datasource Message Flow numberOfSectionsInTableView: tableView:numberOfRowsInSec)on: tableView:cellForRowAtIndexPath:
NSIndexPath • Generic class in Foundation • Path to a specific node in a tree of nested arrays
NSIndexPath and Table Views • Cell location described with an index path
– Section index + row index
• Category on NSIndexPath with helper methods
@interface NSIndexPath (UITableView)
+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section;
@property(nonatomic,readonly) NSUInteger section; @property(nonatomic,readonly) NSUInteger row;
@end
Crea&ng a Table View Programma&cally @interface RootViewController : UIViewController <UITableViewDelegate,
UITableViewDataSource> { NSArray *timeZoneNames; } @property (nonatomic, retain) NSArray *timeZoneNames; @end
- (void)loadView { UITableView *tableView = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain]; tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth; tableView.delegate = self; tableView.dataSource = self; [tableView reloadData]; self.view = tableView; [tableView release]; }
Single Section Table View • Return the number of rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [myStrings count]; }
• Provide a cell when requested
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = ...; cell.textLabel.text = [myStrings objectAtIndex:indexPath.row] return [cell autorelease]; }
Cell Reuse • When asked for a cell, it would be expensive to create a
new cell each time. - (UITableViewCell *)dequeueReusableCellWithIdentifier: (NSString *)identifier; - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@“MyIdentifier”]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:... reuseIdentifier:@“MyIdenifier”] autorelease]; } cell.text = [myStrings objectAtIndex:indexPath.row] return cell; }
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [regions count]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Number of rows is the number of time zones in the region for the specified section. Region *region = [regions objectAtIndex:section]; return [region.timeZoneWrappers count]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { // The header for the section is the region name -- get this from the region at the section index. Region *region = [regions objectAtIndex:section]; return [region name]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *MyIdentifier = @"MyIdentifier”; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease]; } Region *region = [regions objectAtIndex:indexPath.section]; TimeZoneWrapper *timeZoneWrapper = [region.timeZoneWrappers objectAtIndex:indexPath.row]; cell.textLabel.text = timeZoneWrapper.localeName; return cell; }
Triggering Updates • When is the datasource asked for its data?
– When a row becomes visible – When an update is explicitly requested by calling –
reloadData
- (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];
[self.tableView reloadData]; }
Section and Row Reloading - (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections
withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
Calling sequence for inser)ng or dele)ng rows in a table view
Mapping levels of the data model to table views
Additional Datasource Methods
• Titles for section headers and footers • Allow editing and reordering cells
Appearance & Behavior
UITableView Delegate
• Customize appearance and behavior • Keep application logic separate from
view • Often the same object as datasource
Table View Appearance & Behavior • Customize appearance of table view cell
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
• Validate and respond to selection changes
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
Row Selection in Table Views • In iPhone applications, rows rarely stay selected • Selecting a row usually triggers an event
Persistent Selection
Responding to Selection // For a navigation hierarchy... - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Get the row and the object it represents NSUInteger row = indexPath.row id objectToDisplay = [myObjects objectAtIndex:row];
// Create a new view controller and pass it along MyViewController *myViewController = ...; myViewController.object = objectToDisplay;
[self.navigationController pushViewController:myViewController animated:YES]; }
Altering or Disabling Selection - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Don’t allow selecting certain rows? if (indexPath.row == ...) { return nil; } else { return indexPath; }
}
UITableViewController
UITableViewController • Convenient starting point for view controller
with a table view – Table view is automatically created – Controller is table view’s delegate and
datasource
• Takes care of some default behaviors – Calls -reloadData the first time it appears – Deselects rows when user navigates back – Flashes scroll indicators
Table View Cells
Designated Initializer
-‐ (id)initWithFrame:(CGRect)frame reuseIden)fier:(NSString *)reuseIden)fier; DEPRECATED
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier;
Cell Styles UITableViewCellStyleDefault UITableViewCellStyleSubtitle UITableViewCellStyleValue1 UITableViewCellStyleValue2
Basic properties • UITableViewCell has an image view and one or two text
labels
cell.imageView.image = [UIImage imageNamed:@“vitolidol.png”]; cell.textLabel.text = @“Vitol Idol”; cell.detailTextLabel.text = @“Billy Idol”;
Accessory Types // UITableView delegate method - (UITableViewCellAccessoryType)tableView:(UITableView *)table accessoryTypeForRowWithIndexPath:(NSIndexPath *)indexPath;
UITableViewCellAccessoryDisclosureIndicator
UITableViewCellAccessoryDetailDisclosureButton
UITableViewCellAccessoryCheckmark - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
// Only for the blue disclosure button NSUInteger row = indexPath.row; ...
}
Customizing the Content View • For cases where a simple image + text cell doesn’t suffice • UITableViewCell has a content view property
– Add additional views to the content view
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = ...; CGRect frame = cell.contentView.bounds;
UILabel *myLabel = [[UILabel alloc] initWithFrame:frame];
myLabel.text = ...; [cell.contentView addSubview:myLabel];
[myLabel release]; }
• Ques)ons?