In this tutorial we cover the following topics
- 1. General information
- 2. Introduction
- Step 1: create a new project
- Step 2: add Table view and set connection
- Step 3: add a code
- Step 4: using table view cell styles
- Step 5: add an image
- Step 6: handling row selection
- Step 7: disable row selection
- Step 8: delete TableView row when swipe
- 3. Customizing Table View Cells with nib files
- Step 1: create a new project
- Step 2: create a new class
- Step 3: add a new code and a table view
- Step 4: design our table view cell in Interface Builder
- Step 5: run the application
- 4. Customizing Table View Cells with storyboard
- Step 1: create a new project
- Step 2: create a new class
- Step 3: add a new code
- Step 4: add a table view and design our table view cell in the storyboard
- Step 5: run the application
General information
Technically, a table view is the view object that displays a table’s data which is an instance of the class
UITableView
. Each visible row in a table is implemented by an instance of the UITableViewCell
class. Table views are not responsible for storing table’s data. They store only enough data to draw the rows that are currently visible. Table views get their configuration data from an object that conforms to the UITableViewDelegate
protocol and their row data from an object that conforms to the UITableViewDataSource
protocol.
We can also put more data, than standatd title and details one-line strings, in a cell if we need to by adding subviews to UITableViewCell
. We do this using either by adding subviews programmatically when creating the cell or by loading them from a storyboard or nib file.
Table views come in two basic styles
- Grouped A grouped table view contains one or more sections of rows. Within each section, all rows sit tightly together in a nice little group; but between sections, there are clearly visible gaps.
- Plain This is the default style. In this style, the sections are slightly closer together, and each section’s header can optionally be styled in a custom manner. When an index is used, this style is also referred to as indexed.
2. Introduction
- Step 1: create a new project
Create a new project- Select File | New | Project...
- Select Single View Application on the template selection sheet.
- As the product name enter
iOS Table View Basic
- Set the Language to Objective-C, devices pop-up button to Universal and make sure the check box labeled Use Core Data is unchecked.
- Step 2: add Table view and set connections
- Select
Main.storyboard
to edit the storyboard. - Find in the object library a Table View and drag it over to the View window.
- Add all necessary constraints to make sure that the table view is positioned and sized correctly.
- Select the table view in the Document Inspector and bring up the Connections Inspector (use shortcut: Alt + Command + 6).
- Drag from the circle next to dataSource and delegate in Outlets section to the View Controller icon in the Document Outline or above the view controller in the storyboard editor. This makes our controller class both the data source and delegate for this table.
- Select
- Step 3: add a code
- Single-click
ViewController.m
and add the following code
1234567891011121314151617181920212223242526272829303132333435363738394041424344#import "ViewController.h"@interface ViewController () <UITableViewDataSource, UITableViewDelegate>@property NSArray *eightThousandersPeaks;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.eightThousandersPeaks =@[@"Mount Everest", @"K2", @"Kangchenjunga",@"Lhotse",@"Makalu", @"Cho Oyu",@"Dhaulagiri",@"Manaslu", @"Nanga Parbat",@"Annapurna I", @"Gasherbrum I",@"Broad Peak",@"Gasherbrum II", @"Shishapangma"];}- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// Dispose of any resources that can be recreated.}- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {return [self.eightThousandersPeaks count];}- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {static NSString *TableIdentifier = @"TableIdentifier";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:TableIdentifier];if (cell == nil) {cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:TableIdentifier];}cell.textLabel.text = self.eightThousandersPeaks[indexPath.row];return cell;}@end
- Single-click
- Step 4: using table view cell styles
Except the defaultUITableViewCellStyleDefault
theUITableViewCell
class includes several other predefined cell styles that let us easily add a bit more variety to our table views. These cell styles use three different cell elements- Text label This is the cell’s main text. In the case of the default style
UITableViewCellStyleDefault
the text label is the only text shown in the cell. - Detail text label This is the cell’s secondary text, usually used as an explanatory note or label.
- Image If an image is part of the specified style, the image is displayed to the left of the cell’s text.
Let's see all of them
- Single-click
ViewController.m
and to enable detail text label add/modify the following code
1234567891011121314151617181920212223242526272829@interface ViewController () <UITableViewDataSource, UITableViewDelegate>...@property NSArray *eightThousandersPeaksHeight;@end- (void)viewDidLoad {...//Height above mean sea level (AMSL)self.eightThousandersPeaksHeight =@[@"8850", @"8611", @"8586",@"8516",@"8463", @"8201",@"8167",@"8156", @"8126",@"8091", @"8068",@"8047",@"8035", @"8013"];}- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {...if (cell == nil) {cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:TableIdentifier];}...cell.detailTextLabel.text = self.eightThousandersPeaksHeight[indexPath.row];return cell;}
- Let's change table view cell styles again. Single-click
ViewController.m
and to enable detail text label add/modify the following code
1234567...if (cell == nil) {cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1reuseIdentifier:TableIdentifier];}....
- Let's change table view cell styles again. Single-click
ViewController.m
and to enable detail text label add/modify the following code
1234567...if (cell == nil) {cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue2reuseIdentifier:TableIdentifier];}....
- Text label This is the cell’s main text. In the case of the default style
- Step 5: add an image
For all style exceptUITableViewCellStyleValue2
we can add an icon.- Prepare two images: one for selected row and second for not selected. In my case I have two dots (red and green) 24 pixels height and 24 pixels width.
- Drag both files to your project’s Images.xcassets.
- Single-click
ViewController.m
and to enable detail text label add/modify the following code
12345678910111213- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {...UIImage *image = [UIImage imageNamed:@"dot_green"];cell.imageView.image = image;UIImage *highlightedImage = [UIImage imageNamed:@"dot_red"];cell.imageView.highlightedImage = highlightedImage;...}
- Step 6: handling row selection
Now we are going to implement the delegate method that is called after a row has been selected.- Single-click
ViewController.m
and add/modify the following code
12345678910111213141516171819202122- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {NSString *textLabel = self.eightThousandersPeaks[indexPath.row];UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];NSString *detailTextLabel = selectedCell.detailTextLabel.text;NSString *message = [[NSString alloc] initWithFormat:@"You selected %@ (%@)", textLabel, detailTextLabel];UIAlertController *controller =[UIAlertController alertControllerWithTitle:@"Information"message:messagepreferredStyle: UIAlertControllerStyleAlert];UIAlertAction *cancelAction =[UIAlertAction actionWithTitle:@"Close"style: UIAlertActionStyleDefaulthandler: nil];[controller addAction:cancelAction];[self presentViewController:controller animated:YES completion:nil];[tableView deselectRowAtIndexPath:indexPath animated:YES];}
- Single-click
- Step 7: disable row selection
The second table’s delegate method that allow us to handle row selection istableView:willSelectRowAtIndexPath
which is called before the row is selected. It can be used to prevent the row from being selected or even to change which row gets selected.- Single-click
ViewController.m
and add/modify the following code
123456789101112131415- (NSIndexPath *)tableView:(UITableView *)tableViewwillSelectRowAtIndexPath:(NSIndexPath *)indexPath {NSString *detailTextLabel = self.eightThousandersPeaksHeight[indexPath.row];NSNumberFormatter *f = [[NSNumberFormatter alloc] init];f.numberStyle = NSNumberFormatterDecimalStyle;NSNumber *height = [f numberFromString:detailTextLabel];if (height.integerValue < 8500) {return nil;} else {return indexPath;}}
- Single-click
- Step 8: delete TableView row when swipe
- Single-click
ViewController.m
and add/modify the following code
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051@interface ViewController () <UITableViewDataSource, UITableViewDelegate>@property NSArray *eightThousandersPeaksInit;@property NSArray *eightThousandersPeaksHeightInit;@property NSMutableArray *eightThousandersPeaks;@property NSMutableArray *eightThousandersPeaksHeight;@end- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.eightThousandersPeaksInit =@[@"Mount Everest", @"K2", @"Kangchenjunga",@"Lhotse",@"Makalu", @"Cho Oyu",@"Dhaulagiri",@"Manaslu", @"Nanga Parbat",@"Annapurna I", @"Gasherbrum I",@"Broad Peak",@"Gasherbrum II", @"Shishapangma"];self.eightThousandersPeaks = [NSMutableArray arrayWithArray:self.eightThousandersPeaksInit];// or//self.eightThousandersPeaks = [self.eightThousandersPeaksInit mutableCopy];//Height above mean sea level (AMSL)self.eightThousandersPeaksHeightInit =@[@"8850", @"8611", @"8586",@"8516",@"8463", @"8201",@"8167",@"8156", @"8126",@"8091", @"8068",@"8047",@"8035", @"8013"];//self.eightThousandersPeaksHeight = [NSMutableArray arrayWithArray:self.eightThousandersPeaksHeightInit];// orself.eightThousandersPeaksHeight = [self.eightThousandersPeaksHeightInit mutableCopy];}// Override to support conditional editing of the table view.// This only needs to be implemented if we are going to be returning NO// for some items. By default, all items are editable.- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {// Return YES if you want the specified item to be editable.return YES;}// Override to support editing the table view.- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {// Add code here for when you hit delete// Remove the deleted object from your data source.[self.eightThousandersPeaks removeObjectAtIndex:indexPath.row];[self.eightThousandersPeaksHeight removeObjectAtIndex:indexPath.row];[tableView reloadData]; // tell table to refresh now// or//[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];}}
- Single-click
3. Customizing Table View Cells with nib files
There are three basic approaches to create our own table view cells
- one that involves loading a cell from a nib file,
- a second that is similar, but loads the cell from a storyboard,
- and a third that involves adding subviews to UITableViewCell programmatically when creating the cell.
- Step 1: create a new project
Create a new project- Select File | New | Project...
- Select Single View Application on the template selection sheet.
- As the product name enter
iOS Table View Custom Cell Nib
- Set the Language to Objective-C, devices pop-up button to Universal and make sure the check box labeled Use Core Data is unchecked.
- >Step 2: create a new class
- In the Project Navigator, right-click the iOS Table View Custom Cell Nib group and select New File....
- Choose Cocoa Touch Class from the iOS Source section in the template dialog and then press Next
- Name the new class
PeakInfoCell
, make it a subclass ofUITableViewCell
. - Make sure that the Also create XIB file check box is checked this time.
- Press Next and then press Create to save the files.
- Step 3: add a new code and a table view
- Single-click
PeakInfoCell.h
and add/modify the following code
12345678#import <UIKit/UIKit.h>@interface PeakInfoCell : UITableViewCell@property (copy, nonatomic) NSString *name;@property (copy, nonatomic) NSString *height;@end - Single-click
PeakInfoCell.m
and add/modify the following code
12345678910111213141516171819202122232425262728293031323334#import "PeakInfoCell.h"@interface PeakInfoCell ()@property (strong, nonatomic) IBOutlet UILabel *nameLabel;@property (strong, nonatomic) IBOutlet UILabel *heightLabel;@end@implementation PeakInfoCell- (void)awakeFromNib {[super awakeFromNib];// Initialization code}- (void)setSelected:(BOOL)selected animated:(BOOL)animated {[super setSelected:selected animated:animated];// Configure the view for the selected state}- (void)setName:(NSString *)name {if (![name isEqualToString:_name]) {_name = [name copy];self.nameLabel.text = _name;}}- (void)setHeight:(NSString *)height {if (![height isEqualToString:_height]) {_height = [height copy];self.heightLabel.text = _height;}}@end - Single-click
ViewController.h
and add/modify the following code
12345#import <UIKit/UIKit.h>@interface ViewController : UIViewController <UITableViewDataSource>@end - Single-click
ViewController.m
and add/modify the following code
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859#import "ViewController.h"#import "PeakInfoCell.h"static NSString *PeakInfoCellIdentifier = @"PeakInfoCellIdentifier";@interface ViewController ()@property NSArray *eightThousandersPeaks;@property NSArray *eightThousandersPeaksHeight;@property IBOutlet UITableView *tableView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.eightThousandersPeaks =@[@"Mount Everest", @"K2", @"Kangchenjunga",@"Lhotse",@"Makalu", @"Cho Oyu",@"Dhaulagiri",@"Manaslu", @"Nanga Parbat",@"Annapurna I", @"Gasherbrum I",@"Broad Peak",@"Gasherbrum II", @"Shishapangma"];//Height above mean sea level (AMSL)self.eightThousandersPeaksHeight =@[@"8850", @"8611", @"8586",@"8516",@"8463", @"8201",@"8167",@"8156", @"8126",@"8091", @"8068",@"8047",@"8035", @"8013"];UINib *nib = [UINib nibWithNibName:@"PeakInfoCell" bundle:nil];[self.tableView registerNib:nibforCellReuseIdentifier:PeakInfoCellIdentifier];}- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {return [self.eightThousandersPeaks count];}- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {PeakInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:PeakInfoCellIdentifierforIndexPath:indexPath];cell.name = self.eightThousandersPeaks[indexPath.row];cell.height = self.eightThousandersPeaksHeight[indexPath.row];return cell;}- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// Dispose of any resources that can be recreated.}@end - Select
Main.storyboard
to edit the storyboard. - Find in the object library a Table View and drag it over to the View window.
- Add all necessary constraints to make sure that the table view is positioned and sized correctly.
- Now we have to link the table view to the outlet. Select the
Main.storyboard
file and in the Document Outline, Control-drag from the View Controller icon to the Table View icon. Release the mouse and selecttableView
in the pop-up.
- Set our controller class the data source for the table as we did it in part 2 step 2
- Select the table view in the Document Inspector and bring up the Connections Inspector (use shortcut: Alt + Command + 6).
- Drag from the circle next to dataSource in Outlets section to the View Controller icon in the Document Outline or above the view controller in the storyboard editor. This makes our controller class the data source for this table.
- Single-click
- Step 4: design our table view cell in Interface Builder
Create a new project- select
PeakInfoCell.xib
in the Project Navigator to open the file for editing. - Look in the library for a Table View Cell and drag it to the GUI layout area. In my case this cell was already created, so there was no need for manual addition.
- In the the Attributes Inspector set the Identifier value to
PeakInfoCellIdentifier
. - Select the table cell in the editing area to edit our table cell’s content view. Go to the library, drag out two Label controls, and place them in the content view where you want. Next set some font attributes. In my case left label (name label) was set to System Bold 20 and right label (height) to System Italic 17. Remember also to set correct constraints.
- Select the table view cell by clicking PeakInfoCellIdentifier in the Document Outline,
bring up the Identity Inspector, and choosePeakInfoCell
as the Class in Custom Class section.
- Switch to the Connections Inspector, where we will see the
nameLabel
andheightLabel
outlets. Drag from thenameLabel
outlet to the name label (left in my case) and from theheightLabel
outlet to the height label (right).
- select
- Step 5: run the application
4. Customizing Table View Cells with storyboard
We can also design table cells directly in the storyboard, which means that we don’t need to create an extra
nib
file. This is fine as long as we don’t want to share cell designs between different tables.
In this part we will do the same as in previous 3. Customizing Table View Cells with nib files part but without nib files.
- Step 1: create a new project
Create a new project- Select File | New | Project...
- Select Single View Application on the template selection sheet.
- As the product name enter
iOS Table View Custom Cell Storyboard
- Set the Language to Objective-C, devices pop-up button to Universal and make sure the check box labeled Use Core Data is unchecked.
- Step 2: create a new class
- In the Project Navigator, right-click the iOS Table View Custom Cell Storyboard group and select New File....
- Choose Cocoa Touch Class from the iOS Source section in the template dialog and then press Next
- Name the new class
PeakInfoCell
, make it a subclass ofUITableViewCell
. - Press Next and then press Create to save the files.
- Step 3: add a new code
- Single-click
PeakInfoCell.h
and add/modify the following code
12345678#import <UIKit/UIKit.h>@interface PeakInfoCell : UITableViewCell@property (copy, nonatomic) NSString *name;@property (copy, nonatomic) NSString *height;@end - Single-click
PeakInfoCell.m
and add/modify the following code
12345678910111213141516171819202122232425262728293031323334#import "PeakInfoCell.h"@interface PeakInfoCell ()@property (strong, nonatomic) IBOutlet UILabel *nameLabel;@property (strong, nonatomic) IBOutlet UILabel *heightLabel;@end@implementation PeakInfoCell- (void)awakeFromNib {[super awakeFromNib];// Initialization code}- (void)setSelected:(BOOL)selected animated:(BOOL)animated {[super setSelected:selected animated:animated];// Configure the view for the selected state}- (void)setName:(NSString *)name {if (![name isEqualToString:_name]) {_name = [name copy];self.nameLabel.text = _name;}}- (void)setHeight:(NSString *)height {if (![height isEqualToString:_height]) {_height = [height copy];self.heightLabel.text = _height;}}@end - Single-click
ViewController.h
and add/modify the following code
12345#import <UIKit/UIKit.h>@interface ViewController : UIViewController <UITableViewDataSource>@end - Single-click
ViewController.m
and add/modify the following code
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758#import "ViewController.h"#import "PeakInfoCell.h"static NSString *PeakInfoCellIdentifier = @"PeakInfoCellIdentifier";@interface ViewController ()@property NSArray *eightThousandersPeaks;@property NSArray *eightThousandersPeaksHeight;@property IBOutlet UITableView *tableView;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.eightThousandersPeaks =@[@"Mount Everest", @"K2", @"Kangchenjunga",@"Lhotse",@"Makalu", @"Cho Oyu",@"Dhaulagiri",@"Manaslu", @"Nanga Parbat",@"Annapurna I", @"Gasherbrum I",@"Broad Peak",@"Gasherbrum II", @"Shishapangma"];//Height above mean sea level (AMSL)self.eightThousandersPeaksHeight =@[@"8850", @"8611", @"8586",@"8516",@"8463", @"8201",@"8167",@"8156", @"8126",@"8091", @"8068",@"8047",@"8035", @"8013"];}- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {return [self.eightThousandersPeaks count];}- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {PeakInfoCell *cell = [tableView dequeueReusableCellWithIdentifier:PeakInfoCellIdentifier];if (cell == nil) {cell = [[PeakInfoCell alloc]initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:PeakInfoCellIdentifier];}cell.name = self.eightThousandersPeaks[indexPath.row];cell.height = self.eightThousandersPeaksHeight[indexPath.row];return cell;}- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// Dispose of any resources that can be recreated.}@end
- Single-click
- Step 4: add a table view and design our table view cell in the storyboard
- Select
Main.storyboard
to edit the storyboard. - Find in the object library a Table View and drag it over to the View window.
- Add all necessary constraints to make sure that the table view is positioned and sized correctly.
- Find in the object library a Table View Cell and drag it over to the Table View window.
- In the Table View Cell section of Attributes inspector set
- Style as Custom,
- Identifier as
PeakInfoCellIdentifier
.
- Select the table cell in the editing area to edit our table cell’s content view. Go to the library, drag out two Label controls, and place them in the content view where you want. Next set some font attributes. In my case left label (name label) was set to System Bold 20 and right label (height) to System Italic 17. Remember also to set correct constraints.
- Select Main.storyboard, then the table view cell by clicking PeakInfoCellIdentifier in the Document Outline, bring up the Identity Inspector, and choose
PeakInfoCell
as the Class in Custom Class section.
- Switch to the Connections Inspector, where we will see the
nameLabel
andheightLabel
outlets. Drag from thenameLabel
outlet to the name label (left in my case) and from theheightLabel
outlet to the height label (right). - Now we have to link the table view to the outlet. Select the
Main.storyboard
file and in the Document Outline, Control-drag from the View Controller icon to the Table View icon. Release the mouse and selecttableView
in the pop-up. - Set our controller class the data source for the table
- Select the table view in the Document Inspector and bring up the Connections Inspector (use shortcut: Alt + Command + 6).
- Drag from the circle next to dataSource in Outlets section to the View Controller icon in the Document Outline or above the view controller in the storyboard editor. This makes our controller class the data source for this table.
- Select
- Step 5: run the application