Creation Of Tables

Ratings:
(4)
Views:606
Banner-Img
  • Share this blog:

Using Tables with Navigation Bars and Tabs

Almost every application using a table associates that table with a navigation bar. Moreover, in applications of any complexity, the application also usually organizes its tasks into different tabs. For instance, the iPod application has different tabs for different views of its data. The Artists tab, for instance, shows a user’s multimedia sorted by artist. At the iPod application’s top is a navigation bar. When a user selects an artist row, the navigation controller pushes another view onto the navigation controller and displays it. In the following Try This, I try to instill some real-world credibility to this chapter by having you implement a table in a navigation controller that is in a tab-bar tab. Although initially confusing, this is such a common user interface pattern that you should definitely understand the next task. Using a Table in a Navigation Controller in a Tab This is a long, but useful task. Much of it is repetition from previous chapters, but the combination of a table in a navigation controller in a tab is such a common application pattern that it is worth presenting here in detail, even if much of the task is repetitive. Creating and Connecting the Views

  1. Create a new Window-based Name the application TabNavTable.
  2. Add a UITabBarController as an IBOutlet to Name the outlet myCont (Listings 10-23 and 10-24).
  3. Change TabNavTableAppDelegate’s applicationDidFinishLaunching method in TabNavTableAppDelegate to load the newly added tab bar controller’s root view.

 

  1. Save and open xib in Interface Builder.
  2. Add a Tab Bar Controller from the library to the document
  3. Delete the tab bar controller’s root view controller, Selected View Controller (Item 1).
  4. Add a Navigation Controller in the previously deleted root view controller’s place (Figure 10-23).
  5. Change the navigation controller’s view controller, View Controller (Root View Controller), from a UIViewController to a Leave its type as UITableViewController; in a few steps, you change it to your own class, MyTableViewController.
  6. Connect TabNavTableAppDelegate’s myCont property to the tab bar controller (Figure 10-24).
  7. Save and exit Interface builder.
  8. Create a new subclass of Name the class MyTableViewController and add the table view controller methods in Listings 10-25 and 10-26.
  9. Add an NSMutableArray named tableDataList and populate it in MyTableViewController’s viewDidLoad
  10. Create a new empty nib named Open the nib in Interface Builder.
  11. Add a Table View from the library to the document window.

   Slide70  

 Figure 10-23 Navigation controller in place of tab’s view controller

  Slide71

  Figure 10-24 Application with a table, navigation bar, and tab bar

  NOTE In step 14 you are adding the table directly to the nib as the main view. Contrast this with how you added the table view in this chapter’s first Try This example. Both techniques work.  

  1. In the document window, change xib’s File’s Owner to MyTableViewController.
  2. Connect the File’s Owner view outlet to the newly added table view that you added to the document
  3. Connect the table view’s dataSource and delegate outlets to File’s
  4. Save and close xib. Open MainWindow.xib in Interface Builder.
  5. In the document window, expand Tab Bar Controller, and then expand Navigation Controller (Item). Change the Table View Controller (Navigation Item) from a UITableViewController to Don’t forget to change its NIB Name in the Inspector to MyTableViewController to show the table is loaded from another nib.

     Slide72

Figure 10-25 Table in a tab bar

 

  1. Save and exit Interface
  2. Click Build And The first tab contains a navigation bar and a table view (Figure 10-25).

Listing 10-23 TabNavTableAppDelegate.h #import <UIKit/UIKit.h> @interface TabNavTableAppDelegate : NSObject <UIApplicationDelegate> { UIWindow *window; IBOutlet UITabBarController * myCont; } @property (nonatomic, retain) IBOutlet UIWindow *window; @property (nonatomic, retain) IBOutlet UITabBarController * myCont; @end Listing 10-24 TabNavTableAppDelegate.m #import "TabNavTableAppDelegate.h" @implementation TabNavTableAppDelegate @synthesize window; @synthesize myCont;(void)applicationDidFinishLaunching:(UIApplication *)application { [window addSubview: view]; [window makeKeyAndVisible]; }(void)dealloc { [myCont release]; [window release]; [super dealloc]; } @end Listing 10-25 MyTableViewController.h #import <UIKit/UIKit.h> @interface MyTableViewController : UITableViewController { NSMutableArray * tableDataList; } @property (nonatomic, retain) NSMutableArray * tableDataList; @end Listing 10-26 MyTableViewController.m #import "MyTableViewController.h" @implementation MyTableViewController @synthesize tableDataList; - (void) viewDidLoad { NSMutableArray * tempArray = [[[NSMutableArray alloc] initWithObjects:@"Item One", @"Item Two", @"Item Three", @"Item Four", @"Item Five", @"Item Six", @"Item Seven", @"Item Eight", @"Item Nine", @"Item Ten", @"Item Eleven", @"Item Twelve", @"Item Thirteen", @"Item Fourteen", @"Item Fifteen", @"Item Sixteen", @"Item Seventeen", @"Item Eighteen", @"Item Nineteen", @"Item Twenty", nil] autorelease]; self.tableDataList = tempArray; } (NSInteger) tableView : (UITableView *) tableView numberOfRowsInSection: (NSInteger) section { return [self.tableDataList count]; }(UITableViewCell *) tableView : (UITableView *) tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath { UITableViewCell *cell = [tableView   dequeueReusableCellWithIdentifier:@"acell"]; if(cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"acell"] autorelease]; } cell.textLabel.text = [self.tableDataList objectAtIndex:[indexPath row]]; return cell; } - (void)dealloc { [tableDataList release]; [super dealloc]; } @end   Handling Row Selections

  1. Add an IBOutlet to MyTableViewController that references a Name the outlet navCont. Don’t forget to synthesize it and to release it. Save and compile.
  2. Open xib in Interface Builder.
  3. In the document window, expand Tab Bar Controller and then Navigation Controller (Item). Connect MyTableViewController’s navCont outlet to the Navigation Controller (Item).
  4. Save and exit Interface
  5. Click Build And If you completed the steps correctly, there is no change in the application’s appearance.
  6. Create a new UIViewController subclass and name it TableViewDetailsViewController (Listings 10-27 and 10-28). Although you leave this class empty in this task, in a real- world project, this class would contain If you wish, select the checkbox to also create an accompanying xib for the class. If you didn’t already, create a new View xib and name it TableViewDetailsViewController.xib. Open it in Interface Builder.
  7. Change the view’s background
  8. Ensure the File’s Owner class is set to Also ensure the File’s Owner view outlet is connected to the view in the document window.
  9. Save and exit Interface
  10. Open MyTableViewController and import h.
  11. Implement the tableView:didSelectRowAtIndexPath method in MyTableViewController (Listing 10-29).
  12. Build and run in iPhone Upon clicking a row, you are taken to the details page (Figure 10-26).

 

Figure 10-26 Clicking the row takes the user to details view.

  Slide72Slide73     Listing 10-27 TableViewDetailsViewController.h #import <Foundation/Foundation.h> @interface TableViewDetailsViewController : UIViewController { } @end Listing 10-28 TableViewDetailsViewController.m #import "TableViewDetailsViewController.h" @implementation TableViewDetailsViewController @end Listing  10-29 The tableView:didSelectRowAtIndexPath:  method added to MyTableViewController - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath { NSLog(@"pushing..."); TableViewDetailsViewController * temp = [[ [TableViewDetailsViewController alloc] initWithNibName: @"TableViewDetailsViewController" bundle:nil] autorelease]; [self.navCont pushViewController:temp animated:YES]; }  

Editing Table Cells

Table cells can be edited. You can add new rows, delete existing rows, and reorder rows. The way it works is like this: A user clicks a button that puts the table into edit mode. Edit mode displays insert or delete accessories used for adding and deleting rows. These accessories are displayed on a cell’s left side. Editing mode displays reorder accessories on a table cell’s right side.  

Getting to Edit Mode

This chapter ends by discussing how to edit a table. Tables not only display data, they also allow adding rows, deleting rows, and changing the order of rows. A table has two modes: its normal display mode and edit mode. When a table is in edit mode, it can display accessories for inserting, deleting, and rearranging table cells. An application places a table in edit mode by sending a message to the table view’s setEditing:animated: method. For instance, you might call a table’s setEditing:animated: method by implementing an IBAction called by a button on a form. (IBAction) edit { [self.myTableView setEditing:YES animated:YES]; } However, a self-created button is not how tables are usually placed into edit mode. Rather than specifically creating an action and manually calling a method, you usually use a navigation item and let it automatically activate a table view’s edit mode. Remember, 90 percent of the time you will implement a table view in a navigation controller. That navigation controller’s navigation bar can contain a right button. One choice you have when creating a navigation bar button is creating an Edit button. self.navigationItem.rightBarButtonItem = myTableController. editButtonItem; When you set that button to a table controller’s editButtonItem, the controller automatically knows to enter edit mode.  

Edit Mode Methods

tableView:canEditRowAtIndexPath:,tableView:canMoveRowAtIndexPath:,tableView:commitEditing Style:forRowAtIndexPath:,and tableView:commitEditingStyle: forRowAtIndexPath: are four methodsyou should implement in your UITableViewDataSource protocol adoptee. (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath: (NSIndexPath *)indexPath (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath: (NSIndexPath *)indexPath (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle) editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath (UITableViewCellEditingStyle)tableView:(UITableView *) tableView editingStyleForRowAtIndexPath:(NSIndexPath *) indexPath   A table knows a row is editable by the tableView:canEditRowAtIndexPath: method. If you wish all rows to be editable, simply have the method return YES; otherwise, implement code to determine if a particular row is editable. If you omit this method, no rows are editable. The tableView:editingStyleForRowAtIndexPath: method informs the table   what style   editing accessory the row should have. If this method returns a UITableViewCellEditingStyleNone,   Slide74 Figure 10-27 A table where the first and last rows have no editing style,no accessory is displayed. If this method returns  UITableViewCellEditingStyleDelete, the delete accessory is displayed.  And if the method returns UITableViewCellEditingStyleInsert, the insert accessory is displayed. The following example code in Listing 10-30 and Figure 10-27 illustrates.   Listing 10-30 The tableView:editingStyleForRowAtIndexPath method - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { if(indexPath.row == 0 || indexPath.row == [self.workoutArray count]- 1) { return UITableViewCellEditingStyleNone; } return UITableViewCellEditingStyleDelete; }   A table knows a table row is movable by the tableView:canMoveRowAtIndexPath: method. Like the tableView:canEditRowAtIndexPath: method, simply have the method return YES if all rows are moveable; otherwise, write your own custom code. If you omit this method, no rows are movable.The tableView:canMoveRowAtIndexPath: method only prevents particular rows from being directly moved by a user. A user can still move another row to the position held by the unmovable row, thus moving the unmovable row indirectly. To prevent this behavior,you can implement the tableView:targetIndexPathForMoveFromRowAtIndexPath: toProposedIndexPath: method in your table view’s delegate. If a proposed move is acceptable, return the proposedDestinationIndexPath; otherwise, return the sourceIndexPath. The method’s signature follows.   - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath The tableView:commitEditingStyle:forRowAtIndexPath: commits a row insertion or deletion. Notice the editingStyle parameter. If a row is deleted, the table view sends a UITable ViewCellEditingStyleDelete style as the editingStyle parameter. If a row is inserted, the table view sends a UITableViewCellEditingStyleInsert style. It uses the editingStyle parameter to tell it which action resulted in the method being called. This method is for implementing code that handles a row insertion or deletion. For instance, in this chapter, data comes from an NSArray or NSMutableArray. When using an NSMutableArray as a data source for a table, deleting a row means you must delete the corresponding item from the array. If inserting, you must add an item at the index where the row was inserted and remove the item from its old location in the array.

Editing Rows

  1. Copy the TabNavTable project to a new location and open it in Xcode.
  2. Create a new view controller class called AddItemViewController (Listings 10-31 and 10- 32). If you wish, select the ―With XIB for user interface‖ checkbox and create an associated
  3. Add a reference to MyTableViewController in AddItemViewController; however, instead of importing MyTableViewController, use the @class macro (Listings 10-33 and 10-34). Name the property
  4. Add an IBOutlet for a Name the text field addedName. Add an IBOutlet for a bar button item. Name the button doneButton. Do not forget to synthesize the outlets/ properties.
  5. Add an IBAction called exit and Save.

 

  1. Open MyTableViewController and import Add a property referencing the AddItemViewController. Name the reference addItemController. Also, add a method named exitAndSave and an IBAction named enterAddMode. Note that exitAndSave takes an NSString as a parameter and is not an IBAction.
  2. Add an IBOutlet for a bar button item named
  3. Change the viewDidLoad method so that it sets its navigation item’s rightBarButtonItem to

its editButtonItem and its navigation item’s leftBarButtonItem to addButton.

  1. Implement the UITableViewDataSource protocol methods: tableView: canEditRowAtIndexpath:, tableView:commitEditingStyle:forRowAtIndex:, tableView: moveRowAtIndexPath:toIndexPath:, tableView: editingStyleForRowAtIndexPath:, and tableView:canMoveRowAtIndexPath:.
  2. If you didn’t already when creating the view controller, create a new View XIB named xib. Open the nib in Interface Builder.
  3. Ensure the File’s Owner is an AddItemViewController, if it is not set it to this Ensure its view is connected to the view in the document window.
  4. Add a bar button item to the document Change the newly added bar button’s identifier to Done.
  5. Connect the File’s Owner doneButton outlet to the newly created Done
  6. Add a UITextField to the Attach it to the File’s Owner addedName outlet.
  7. Connect the File’s Owner exitAndSave action to the newly added Done bar button
  8. Save and exit Interface
  9. Open AddItemViewController and implement the viewDidLoadMethod so that it initializes its navigationItem’s title to ―Add Item‖ and its rightBarButtonItem to its
  10. Open xib in Interface Builder and add a bar button item to the document window. Change the button’s identifier to Add.
  11. Connect the File’s Owner enterAddMode property to the newly added bar button Also connect the File’s Owner addButton to the newly added bar button item.
  12. Return to MyTableViewController  and implement the exitAndSave  and the enterAddMode methods like Listing 10-32.
  13. Return to AddItemViewController and implement the exitAndSave method like Listing 10-34.
  14. Ensure all your properties are being properly released in each class dealloc
  15. Save and exit Interface
  16. Click Build And Go.

     Slide75        

 Figure 10-28 The table view in edit mode

  When the application starts, it presents the user with the table view. Upon tapping the Edit button, the application presents the table in edit mode (Figure 10-28). If the user clicks one of the table’s delete accessories, the accessory rotates 90 degrees and presents a Delete button (Figure 10-29). Upon clicking Delete, the row is deleted. When a user clicks and drags the move accessory on the right, he or she can move the row to the new location desired (Figure 10-30).   If a user decides to add a row, he or she taps the Add button, which presents the user with a view to enter the new object’s details (Figure 10-31). If the user decides to cancel this action, he or she simply taps the Back button. If the user decides to save the record, he or she taps the Done button, which saves the record and returns the user to the table with the newly added table row (Figure 10-32). To support moving rows, you implemented the tableView:moveRowAtIndexPath: toIndexPath: method. In that method, you obtained the object from its old position in the tableDataList, removed it, and then added it to its new location. You also implemented the tableView:canMoveRowAtIndexPath: and tableView:canEditRowAtIndexPath: methods. If you needed to only allow certain rows to be editable, you would add that code to the tableView:canEditRowAtIndexPath: method. If you needed to only allow certain rows to be movable, you would add code to the tableView:canMoveRowAtIndexPath: method. Here, both methods simply return YES.     Slide75Slide76

           Figure 10-29 Deleting a row                                                                                         Figure 10-30 Moving a row

    Slide76Slide77

           Figure 10-31 Adding an item                                                               Figure 10-32 The table view with thenewly added item

    Supporting delete functionality requires a little more code than moving rows, but not much. You implemented the tableView:commitEditingStyle:forRowAtIndexPath: method. In the example, this method removes an object from the index and deletes the row from the table. Notice you disallowed inserting rows by implementing the tableView:editingStyleForRow AtIndexPath: and having it return UITableViewCellEditingStyleDelete. This method informs a table what accessory, if any, it should display in a row when the table enters edit mode. Here, it displays the delete accessory.You did not implement insert functionality at all. Inserting uses similar logic to deleting a row, only the style is UITableViewCellEditingStyleInsert. You would also implement code to initialize an object and then insert it in the data source at the proper location. For instance, in the previous example, you could change it to support inserting rows if you changed tableView: editingStyleForRowAtIndexPath: to return UITableViewCellEditingStyleInsert and added the following lines to the tableView:commitEditingStyle:forRowAtIndex: method: else if (editingStyle == UITableViewCellEditingStyleInsert) { self.tableDataList insertObject:@"Uninitialized" atIndex:indexPath. row]; [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; } In this example, however, adding a row does not use a table’s edit mode. Although it is possible to insert a row using a table’s edit mode, it is often not practical. Usually, a table lists items, where each row represents an individual item. Because each item has details associated with it, adding is often accomplished using a separate view controller. Here, you added a left bar button with an addition symbol. When a user clicks the button, it calls MyTableViewController’s enterAddMode method. This method presents the AddItemViewController’s view. Note that AddItemViewController and MyTableViewController both have references to each other. Upon finishing entering the new item, a user clicks Done, and the Done button fires AddItemViewController’s exitAndSave method. This method calls MyTableViewController’s exitAndSave method. and the row is added as the table’s last row. Listing 10-31 MyTableViewController.h #import <UIKit/UIKit.h> #import "TableViewDetailsViewController.h" #import "AddItemViewController.h" @interface MyTableViewController : UITableViewController { NSMutableArray * tableDataList; IBOutlet UINavigationController * navCont; AddItemViewController * addItemController; IBOutlet UIBarButtonItem * addButton; } @property (nonatomic, retain) UINavigationController * navCont; @property (nonatomic, retain) NSMutableArray * tableDataList; @property (nonatomic, retain) AddItemViewController * addItemController; @property (nonatomic, retain) UIBarButtonItem * addButton; (IBAction) exitAndSave: (NSString *) newValue; (IBAction) enterAddMode: (id) sender; @end Listing 10-32 MyTableViewController.m #import "MyTableViewController.h" @implementation MyTableViewController @synthesize tableDataList; @synthesize navCont; @synthesize addItemController; @synthesize addButton; - (IBAction) enterAddMode: (id) sender { self.addItemController = [[[AddItemViewController alloc] initWithNibName: @"AddItemViewController" bundle:nil] autorelease]; [self.navCont pushViewController:self.addItemController animated:YES];   self.addItemController.parentTable = self;} (void) exitAndSave : (NSString *) newValue { [self.tableDataList addObject: newValue]; [self.navCont popToRootViewControllerAnimated:YES]; [self.tableView reloadData]; }(void) viewDidLoad { NSMutableArray * tempArray = [[[NSMutableArray alloc] initWithObjects: @"Item One", @"Item Two", @"Item Three", @"Item Four", @"Item Five", @"Item Six", @"Item Seven", @"Item Eight", @"Item Nine", @"Item Ten", @"Item Eleven", @"Item Twelve", @"Item Thirteen", @"Item Fourteen", @"Item Fifteen", @"Item Sixteen", @"Item Seventeen", @"Item Eighteen", @"Item Nineteen", @"Item Twenty", nil] autorelease]; self.tableDataList = tempArray; self.navigationItem.rightBarButtonItem = self.editButtonItem; self.navigationItem.leftBarButtonItem = self.addButton; }(NSInteger) tableView : (UITableView *) tableView numberOfRowsInSection: (NSInteger) section { return [self.tableDataList count]; }(UITableViewCell *) tableView : (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"acell"]; if(cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"acell"] autorelease]; } cell.textLabel.text = [self.tableDataList objectAtIndex:[indexPath row]]; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath { TableViewDetailsViewController * temp = [[ [TableViewDetailsViewController alloc] initWithNibName: @"TableViewDetailsViewController" bundle:nil] autorelease]; [self.navCont pushViewController:temp animated:YES]; } - (void)tableView:(UITableView *)tableView commitEditingStyle: (UITableViewCellEditingStyle)editingStyle forRowAtIndexPath: (NSIndexPath *) indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [self.tableDataList removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; } else if (editingStyle == UITableViewCellEditingStyleInsert) { [self.tableDataList insertObject:@"Uninitialized" atIndex:indexPath. row];   [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; } } - (void)tableView:(UITableView *)tableView moveRowAtIndexPath: (NSIndexPath *) fromIndexPath toIndexPath:(NSIndexPath *) toIndexPath { id object = [[self.tableDataList objectAtIndex:fromIndexPath.row] retain]; [self.tableDataList removeObjectAtIndex:fromIndexPath.row]; [self.tableDataList insertObject:object atIndex: toIndexPath.row]; [object release]; } -(UITableViewCellEditingStyle) tableView: (UITableView *) tableView editingStyleForRowAtIndexPath: (NSIndexPath *) indexPath { return UITableViewCellEditingStyleDelete; }(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath: (NSIndexPath *) indexPath { return YES; }(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath: (NSIndexPath *) indexPath { return YES; }(void)dealloc { [tableDataList release]; [navCont release]; [addItemController release]; [addButton release]; [super dealloc]; } @end Listing 10-33 AddItemViewController.h #import <UIKit/UIKit.h> @class MyTableViewController; @interface AddItemViewController : UIViewController { MyTableViewController * parentTable; IBOutlet UITextField * addedName; IBOutlet UIBarButtonItem * doneButton; } @property (nonatomic, retain) UITextField * addedName; @property (nonatomic, retain) MyTableViewController * parentTable; @property (nonatomic, retain) IBOutlet UIBarButtonItem * doneButton; - (IBAction) exitAndSave: (id) sender; @end Listing 10-34 AddItemViewController.m #import "AddItemViewController.h" @implementation AddItemViewController@synthesize addedName; @synthesize parentTable; @synthesize doneButton; @synthesize addedName; (void) viewDidLoad { navigationItem.title = @"Add Item"; self.navigationItem.rightBarButtonItem = self.doneButton; } (void)dealloc { [parentTable release]; [doneButton release]; [addedName release]; [super dealloc]; }(IBAction) exitAndSave: (id) sender { [self.parentTable exitAndSave:self.addedName.text]; } @end

You liked the article?

Like : 0

Vote for difficulty

Current difficulty (Avg): Medium

Recommended Courses

1/15

About Author
Authorlogo
Name
TekSlate
Author Bio

TekSlate is the best online training provider in delivering world-class IT skills to individuals and corporates from all parts of the globe. We are proven experts in accumulating every need of an IT skills upgrade aspirant and have delivered excellent services. We aim to bring you all the essentials to learn and master new technologies in the market with our articles, blogs, and videos. Build your career success with us, enhancing most in-demand skills in the market.


Stay Updated


Get stories of change makers and innovators from the startup ecosystem in your inbox