Grouping and Indexing

22 September, 2018


Related Blogs

Tables have two main styles: grouped and plain. Figure 10-3 illustrates a table with a plain style, while Figure 10-4 illustrates a table with a grouped style. Plain tables might also be indexed. An index sorts the rows and makes navigation quicker by letting a user jump to different locations in the index.

Grouped Table Style

Grouping is accomplished by changing a UITableView’s style to grouped. You then tell a UITableView’s data source how many sections belong in the table and how many rows belong in each section. The class adopting the UITableViewDataSource protocol informs the table how many sections via the numberOfSectionsInTableView method. It informs the table how many rows are in each section via the tableView:numberOfRowsInSection: method.

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
  • (NSInteger)tableView:(UITableView *) tableView numberOfRowsInSection: (NSInteger)section

Each grouping might have a title. You add titles by having your UITableViewDataSource protocol adoption implement the tableView:titleForHeaderInSection method. This method provides a table view with a title for a section’s header. You might also wish adding a footer to each grouping by implementing the tableView:titleForFooterInSection: method.

  • (NSString *)tableView:(UITableView *)tableView titleForHeaderIn Section:(NSInteger)section
  • (NSString *)tableView:(UITableView *)tableView titleForFooterIn Section:(NSInteger)section


  1. Copy TableProjectOne from the first task to a new Open the newly copied TableProjectOne in Xcode.
  2. Modify the array in TableHandler so tableDataList consists of an array of five arrays (Listing 10-10).
  3. Add the numberOfSectionsInTableView and titleForHeaderInSection methods to m (Listing 10-11).
  4. Modify numberOfRowsInSection to return 2.
  5. Modify cellForRowAtIndexPath so it uses the section and the row (Listing 10-12).
  6. Open xib in Interface Builder.
  7. Change the table view’s Style from Plain to Grouped (Figure 10-12).
  8. Save and exit Interface Click Build And Go. The table’s rows are grouped (Figure 10-13).

  The fillList method initializes an NSArray of five NSArrays. The numberOfSectionsInTable View method simply returns five. Although not realistic, this number matches the number of data arrays (tempArrayA through tempArrayB). The tableView:titleForHeaderInSection is hard-coded to return A, B, C, D, or E, depending upon the current section. When the table loads, five sections are created, each with a title from the titleForHeaderInSection method. Each row’s content is determined from the cellForRowAtIndexPath method.    Slide64 - CopySlide62                              Figure 10-13 The application running in iPhone Simulator   Listing 10-10 Table’s list modified to an array of arrays(void) fillList { NSArray * tempArrayA = [[[NSArray alloc] initWithObjects:@"AItem One", @"AItem Two", nil] autorelease]; NSArray * tempArrayB = [[[NSArray alloc] initWithObjects:@"BItem Three", @"BItem Four", nil] autorelease]; NSArray * tempArrayC = [[[NSArray alloc] initWithObjects:@"CItem Five", @"CItem Six", nil] autorelease]; NSArray * tempArrayD = [[[NSArray alloc] initWithObjects:@"DItem Seven", @"DItem Eight", nil] autorelease]; NSArray * tempArrayE = [[[NSArray alloc] initWithObjects:@"EItem Nine", @"EItem Ten", nil] autorelease]; NSArray * tempArray = [[[NSArray alloc] initWithObjects:tempArrayA, tempArrayB, tempArrayC, tempArrayD, tempArrayE, nil] autorelease]; self.tableDataList = tempArray; } Listing 10-11 Modifications to TableHandler.m to support grouping

  • (NSInteger) numberOfSectionsInTableView: (UITableView *) tableView { return 5;


  • (NSString *) tableView: (UITableView *) tableView titleForHeaderInSection: (NSInteger) section {

switch (section) { case 0: return @"A"; break; case 1: return @"B"; break; case 2: return @"C"; break; case 3: return @"D"; break; case 4: return @"E"; break;}   return nil; }(NSInteger) tableView : (UITableView *) tableView numberOfRowsInSection: (NSInteger) section { return 2; } Listing 10-12 The cellForRowAtIndexPath modified to use row and section(UITableViewCell *) tableView : (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"acell"]; if(cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyle Default reuseIdentifier: @"acell"] autorelease]; } cell.textLabel.text = [[self.tableDataList objectAtIndex:indexPath. section] objectAtIndex:indexPath.row]; return cell; }


Tables can be indexed. To index a table, a table’s style should be plain. As with grouping, you implement the numberOfSectionsInTableView: and tableView:numberOfRowsInSection: methods, but you also implement a third method: sectionIndexTitlesForTableView:. This method, implemented in your UITableViewDataSource adoptee, creates the titles that appear along a table’s right side. Upon clicking one of these values, a user is taken directly to the group with the corresponding title. - (NSArray *) sectionIndexTitlesForTableView:(UITableView *) tableView


  1. Open the TableProjectOne from the grouping Try This task.
  2. Open xib and change the table view’s style to Plain.
  3. Save and exit Interface Click Build And Go. Notice the application is still grouped, but the table’s appearance is changed (Figure 10-14).

Figure 10-14 A plain table with groupings

    New Microsoft PowerPoint Presentation    

  1. Implement the sectionIndexTitlesForTableView method, as in Listing 10-13, in m.
  2. Click Build And The application has an index (Figure 10-15).

Listing 10-13 The sectionIndexTitlesForTableView method(NSArray *) sectionIndexTitlesForTableView: (UITableView *) tableView { NSArray * keys = [[[NSArray alloc] initWithObjects: @"A", @"B", @"C", @"D", @"E",nil] autorelease];   return keys; }   New Microsoft PowerPoint Presentation  

  Figure 10-15 The indexed table running in iPhone Simulator

NOTE Don’t let this chapter’s reliance on simple NSArrays fool you into thinking you must use this collection class to hold a table’s data. You can use any collection class, or any other method you deem appropriate, provided you implement methods to obtain the data correctly.

Images in Tables

Adding an image to a table, provided you are happy with the image appearing in the row’s upper-left corner, is not difficult. Simply add an image to the cell in the tableView: cellForRowAtIndexPath: method. Remember, this method loads a UITableViewCell into a row. You can use this method to initialize a table cell with an image using the UITableViewCell’s imageView.image property. The image is then displayed in the table’s row.

Adding an Image

  1. Open the last task’s From the book’s Resources folder, add the images power.png,icon.png, package.png, web.png, and colorize.png to the project’s Resources folder.
  2. Modify the tableView:cellForRowAtIndexPath: method to match Listing 10-14.
  3. Click Build And Notice the images overrun the table cell bounds (Figure 10-16).

  Listing 10-14 The tableView:cellForRowAtIndexPath: method added to TableHandler.m - (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. section] objectAtIndex: indexPath.row]; UIImage * image; switch (indexPath.section) { case 0: image = [UIImage imageNamed:@"power.png"]; break; case 1: image = [UIImage imageNamed:@"Icon.png"]; break; case 2: image = [UIImage imageNamed:@"package_graphics.png"]; break; case 3: image = [UIImage imageNamed:@"colorize.png"]; break; case 4: image = [UIImage imageNamed:@"web.png"]; break; } cell.imageView.image = image; return cell; }

  1. Scale the images in Make the images 32 × 32 pixels.
  2. Re-import the images into the
  3. Click Build And The images display correctly (Figure 10-17).

Figure 10-16 Images are too large to display in the application’s table rows.


 Figure 10-17 Resized images displayed correctly


Selecting Rows

The UITableView allows you to select a row. Typically, a table presents rows to a user, where each row is an item in a hierarchical list. Upon selecting a row, the user is generally taken to another view presenting the item’s details. You implement the tableView: willSelectRowAtIndex: and tableView:didSelectRowAtIndexPath: methods if you wish to allow a user to select a row. (NSIndexPath *) tableView:(UITableView *) tableView willSelectRowAtIndexPath: (NSIndexPath *) indexPath(void) tableView:(UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath The tableView:willSelectRowAtIndexPath: method allows the delegate to react to a row about to be selected. The tableView:didSelectRowAtIndexPath: method allows a reactionto a row’s selection. These methods are useful because they allow you to implement custom behavior in a table’s delegate when a row is selected.

Row Selection

  1. Open the last task’s project in Xcode.
  2. Add the tableView:willSelectRowAtIndexPath: and the tableView: didSelectRowAtIndexPath: methods in Listing 10-15 to m.
  3. Click Build And The application looks the same as the previous task’s results. Clicking the items should result in logging similar to Listing 10-16.

Listing 10-15 The tableView:willSelectRowAtIndexPath: and tableView: didSelectRowAtIndexPath: methods -(NSIndexPath *) tableView: (UITableView *) tableView willSelectRowAt IndexPath: (NSIndexPath *) indexPath { NSLog(@"I selected the item at the %d array and %d item, the value is: %@", indexPath.section, indexPath.row, [[self.tableDataList objectAtIndex: indexPath.section] objectAtIndex: indexPath.row]); return indexPath; } -(void)tableView:(UITableView *) tableView didSelectRowAtIndexPath: (NSIndexPath *) index { NSLog(@"Yes I did...."); } Listing 10-16 Debugger Console logging [Session started at 2009-01-09 13:25:41 -0500.] 2009-01-09 13:25:45.453 TableProjectOne[2089:20b] I selected the item at the 0 array and 0 item, the value is: AItem One 2009-01-09 13:25:45.454 TableProjectOne[2089:20b] Yes I did.... 2009-01-09 13:25:48.372 TableProjectOne[2089:20b] I selected the item at the 1 array and 0 item, the value is: BItem Three 2009-01-09 13:25:48.373 TableProjectOne[2089:20b] Yes I did.... Changing Row Height A couple of sections ago, you added images that were too large to display in a table’s row. The correct way to fix this is usually to resize the images. However, sometimes you want to display a larger image, text with a large font, or a custom cell. One way you can add space in a table’s row is by increasing the row’s height. You increase a row’s height using the heightForRowAtIndexPath method. Changing Row Height

  1. Open the previous task project in Xcode.
  2. Add the heightForRowAtIndexPath: method in Listing 10-17 to m.
  3. Click Build And Go, and the rows are 90 pixels tall (Figure 10-18).


Figure 10-18 The application running with 90-pixel-high rows in iPhone Simulator

  New Microsoft PowerPoint Presentation

  Listing 10-17 The heightForRowAtIndexPath method added to TableView

-(CGFloat) tableView : (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath { return 90; } Accessorizing Table Cells You can tell a cell to place a check mark, disclosure arrow, or detailed disclosure button in the cell by setting the cell’s accessoryView or accessoryType properties. Accessories are visual user interface clues for users. For instance, the check mark might inform a user that he or she has already selected a row. A disclosure arrow or a detailed disclosure button might hint to a user that he or she can select the row to view the row’s details in another view. The check mark and disclosure button are visual clues for a user and do not provide events that respond to a user tapping them. However, the detailed disclosure button can respond to a user tapping it.

Accessorizing a Table Cell

  1. Open the previous project in Xcode and comment the section Index Titles For TableView method in m.
  2. Add the tableView:accessoryButtonTappedForRowWithIndexPath: method to m(Listing10-18).Also modify the tableView:cellForRowAtIndexPath: method to add the accessories to the table cells.
  3. Click Build And The rows contain accessories (Figure 10-19). When you tap the detailed disclosure button, the table calls the tableView:accessoryButtonTappedForRow WithIndexPath: method.

  Listing  10-18 The tableView:cellForRowAtIndexPath: and tableView:accessoryButton TappedForRowWithIndexPath: methods - (UITableViewCell *) tableView : (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { NSUInteger section = [indexPath section]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: @"acell"];     Slide66

  Figure 10-19 Accessorized table rows

if(cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"acell"] autorelease]; } cell.textLabel.text = [[self.tableDataList objectAtIndex:section] objectAtIndex:[indexPath row]]; UIImage * image; switch (indexPath.section) { case 0: image = [UIImage imageNamed:@"power.png"]; break; case 1: image = [UIImage imageNamed:@"Icon_resize.png"]; break; case 2: image = [UIImage imageNamed:@"package_graphics_resize.png"]; break; case 3: image = [UIImage imageNamed:@"colorize.png"]; break; case 4: image = [UIImage imageNamed:@"web.png"]; break; } cell.imageView.image = image; if(indexPath.section == 0) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } else if(indexPath.section == 1) { cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; } else { cell.accessoryType = UITableViewCellAccessoryCheckmark; } return cell; } -(void)    tableView:(UITableView    *)    tableView    accessoryButtonTappedForRowWithIndexPath: (NSIndexPath *) indexPath { NSLog(@"hey now...."); }  

Customizing a Table Cell

Tables can be customized. Sometimes you might wish to format data differently than provided by the default UITableViewCell. The most direct way to accomplish formatting a table cell is by adding a view to the UITableViewCell. You do this in code, by adding a subview to a cell when initializing it in the tableView:cellForRowAtIndexPath method. Another technique is to create a subclass of a UITableViewCell and then create its graphical layout using Interface Builder.

Customizing a Cell Using Interface Builder

  1. Create a new Navigation-based Name the application CustomizedCell.
  2. Create a new subclass of Note that Xcode provides a template for this class. Name the class MyCellView. Be certain to deselect the Use Core Data for storage checkbox if selected.
  3. In MyCellView, create a new UILabel outlet named theTextLabel (Listings 10-19 and 10- 20).
  4. Click Save And
  5. Drag the image png from this book’s Resources folder to the Resources folder in theproject. Save.
  1. Create a new Empty Name the file MyCellView.xib and open it in Interface Builder.
  2. Add a Table View Cell from the library to the document window.


  1. Change the cell’s class from UITableViewCell to
  2. Double-click My Cell View in the document window to open the cell’s
  3. In the Inspector, select png as the cell’s image. Change the cell’s background to yellow. Also, be certain to set the Identifier to MyCell (Figure 10-20).

Figure 10-20 Setting the identifier to MyCell

  Slide67     Slide68  

 Figure 10-21 Adding UIImageView and UILabels to a view canvas

 CAUTION If you do not set a cell’s identifier, the cell can never be reused. This means every call to tableView:cellForRowAtIndexPath: results in a new table cell.

  1. Drag a UIImageView and two UILabels to the canvas (Figure 10-21). Type some text in one label; delete the other label’s Set the image view’s image to money.png.
  2. Connect the MyCellView’s theTextLabel outlet to the newly added
  3. Save and exit Interface
  4. Open xib in Interface Builder and change the table view’s background to yellow. Save and exit Interface Builder.
  5. Modify RootViewController to implement the UITableViewController methods needed so they match Listings 10-21 and 10-22.
  6. Modify the tableView:cellForRowAtIndexPath: method to set the cell’s accessory, background color, and
  7. Click Build And The table cells have the customized appearance (Figure 10-22).

Listing 10-19 MyCellView.h #import <UIKit/UIKit.h> @interface MyCellView : UITableViewCell { IBOutlet UILabel * theTextLabel; } @property (nonatomic, retain) IBOutlet UILabel * theTextLabel; @end   Listing 10-20 MyCellView.m #import "MyCellView.h" @implementation MyCellView @synthesize theTextLabel;   - (void)dealloc { [theTextLabel release]; [super dealloc]; } @end Listing 10-21 RootViewController.h #import <UIKit/UIKit.h> #import "MyCellView.h" @interface RootViewController : UITableViewController { } @end  

Figure 10-22 Application with background color

  Slide69   Listing 10-22 RootViewController.m #import "RootViewController.h" #import "CustomizedCellAppDelegate.h" @implementation RootViewController

  • (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; }
  • (NSInteger)tableView: (UITableView *) tableView numberOfRowsInSection: (NSInteger) section { return 5; }
  • (CGFloat) tableView : (UITableView *) tableView heightForRowAtIndexPath: (NSIndexPath *) indexPath { return 110; }
  • (UITableViewCell *)tableView:(UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { MyCellView *cell = (MyCellView *) [tableView dequeueReusableCellWithIdentifier: @"MyCell"];

if(cell == nil) { cell = [[[NSBundle mainBundle] loadNibNamed:@"MyCellView" owner:self options:nil] objectAtIndex:0]; } [cell.theTextLabel setText:@"Just some static text."]; NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"money" ofType:@"png"]; cell.imageView.image = [UIImage imageWithContentsOfFile:imagePath]; [cell setAccessoryType:UITableViewCellAccessoryCheckmark]; cell.contentView.backgroundColor = [UIColor yellowColor]; cell.backgroundView.backgroundColor = [UIColor yellowColor]; return cell; } - (void)dealloc { [super dealloc];}@end   Notice in the previous example that you initialize the cell every time it’s called in the tableView:CellForRowAtIndexPath: method. This initialization is per Apple’s documentation, Table View Programming Guide for iPhone OS. The ―tableView:cellForRowAtIndexPath should always reset all content when reusing a cell.‖ That is why in the tableView: cellForRowAtIndexPath: you set the cell’s background color, image, and label text. In a more realistic example, you would probably vary a cell’s content depending upon the row. Implementing a UITableViewCell in its own nib does not require implementing a UITableViewCell class, as you did in the example. However, if you wish to override a UITableViewCell’s method, such as setSelected, you must implement your own custom class. You then set the UITableViewCell’s type in Interface Builder to be your custom subclass. In this example, that class is MyCellView. Implementing a custom UITableViewCell subclass is also a convenient location to place IBOutlets and IBActions for the controls on your custom UITableViewCell control. NOTE For more information on table-view cells, refer to the "A Closer Look at Table-View Cells" in Apple’s "Table View Programming Guide" for iPhone OS.

About Author


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 .