In this article, we will experiment with some of the concepts we have learnt in my previous articles with an example. We will also learn about table views.
I have downloaded XCode 5 with iOS 7 SDK from the Appstore. I would advise you to download the XCode 5 so that we could be on the same page before we begin to create our sample application.
Let us now create a simple list application.
Create a New Application ‘SampleListApp’ using the ‘Empty Application’ template.
Right click on the Project in the Navigator. Select ‘New File’ option.
Select ‘Objective-C-class’ template
Enter the name of the custom view controller ‘SPTTableViewController’.
We will display a list in this view. So, the custom view controller should be a subclass of ‘UITableViewController’.
Select ‘With XIB for User Interface’ option and Click ‘Next’
Select the file location and Click on ‘Create’.
Now the View Controller Source files and XIB will be created.
Remember, user interfaces can be created programmatically or by using XIB or Storyboard. Use of Storyboards is common and easy after its introduction in iOS 5. But knowledge of creating UI through XIB is also important. So we will use XIB to create UI until we learn about Storyboards.
Let us create an array of objects and populate in the table view.
Add this line in the ‘SPTTableViewController.h’ file
@property (nonatomic,strong) NSArray *arrItems;
Add this line in the ‘SPTTableViewController.m’ file
@synthesize arrItems;
Initialize the array in the ‘viewDidLoad’ method
- (void)viewDidLoad
{
[super viewDidLoad];
arrItems = [[NSArray alloc] initWithObjects:@"Item 1",@"Item 2",@"Item3", nil];
}
Select ‘SPTTableViewController.xib’. Note that a tableview is created and added as the view outlet of ‘SPTTabeViewController’ class.
Note that the datasource and delegate outlets are also mapped to the File Owner.
This means that it is the responsibility of the ‘SPTTableViewController’ class to define the number of rows or sections in a table view and to decide on what should happen when the list item or table view row is selected or clicked.
A protocol is used to declare methods and properties independent of any class.
If ‘object A’ delegates certain actions to ‘Object B’, then Object B should conform to the protocol of Object A.
In our example, tableview has delegated certain actions to ‘SPTTableViewController’ and hence the controller should conform to ‘UITableViewDataSource’ and ‘UITableViewDelegate’ protocols. Technically, ‘SPTTableViewController’ should implement ‘UITableViewDataSource’ and ‘UITableViewDelegate’ protocol methods.
These methods are auto generated by the XCode and added to the SPTTableViewController.m file.
UITableViewDataSource
1. Method to define the number of sections in a table view
We will create a table view with one section.
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
2. Method to define the number of rows in each section
The number of rows in the section should be the number of objects in the array ‘arrItems’
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [arrItems count];
}
3. ‘NSIndexpath’ refers to an object that represents the section and row in a tableview. The method below is used to configure a cell at the given indexpath.
When we create a tableviewcell we give an identifier to represent the cell. We usually give different cell identifier if the layout of the cell is different. Otherwise, a single cell identifier is used to represent cells with similar layout.
If a table view has thousands of rows and only if ten rows are visible then only 10 cell objects will be created. When the user scrolls, ‘dequereusableidentifier’ method tries to reuse the pre-existing cell with the given cell identifier, there by optimizing the memory usage. For example, If 10 cells are visible in a table view, and the user scrolls to view the 11th cell, the first cell will not be visible at that time and hence the 11th cell is not newly created rather the first cell is reused.
If there are no cells to reuse (should be the first 10 cells), then a new cell is created with a default style and an identifier is set to represent the cell.
There are four ready-to-use tableviewcell styles. One of them is ‘UITableViewStyleDefault’ which will have a label and an optional image in the left side.
We will populate the cell label with the objects in the array ‘arrItems’
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.textLabel.text = [arrItems objectAtIndex:indexPath.row];
return cell;
}
UITableViewDelegate
This method is used to navigate to the next view when you select or click an item in the table view.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here, for example:
// Create the next view controller.
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
// Pass the selected object to the new view controller.
// Push the view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
Check the other protocol methods and its description in the ‘SPTTableViewController.m’ file.
Now, let us create a navigation controller and add the table view controller created above as its root view controller. We will add this navigation controller to the appdelegate’s window object.
Change your appdelegate header and implementation files as given below
SPTAppDelegate.h
#import <UIKit/UIKit.h>
@class SPTTableViewController;
@interface SPTAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UINavigationController *navController;
@property (strong, nonatomic) SPTTableViewController *vController;
@end
SPTAppDelegate.m
#import "SPTAppDelegate.h"
#import "SPTTableViewController.h"
@implementation SPTAppDelegate
@synthesize navController,vController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
vController = [[SPTTableViewController alloc] initWithNibName:@"SPTTableViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:vController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
Now run the application on iOS 7 simulator
Now change the number of sections to ‘2’ and run the application.
The indexpath object will have the section and row values as below
First Section (0,0),(0,1),(0,2)
Second Section (1,0)(1,1),(1,2)
Since we are displaying the array objects based on the row property of the indexpath, the values are repeated.
Where is the sectional division? To differentiate between the sections in a table view, we should change the style of the table view.
Change the style in the .xib file as given below and run the application in the simulator.
Conclusion
We have learnt about table view and its delegates and protocols. We will extend this example and see how we can navigate between view controllers in my next article.