×

iOS UITableView


What is UITableView ?

UITableView is used to show the list of contents . Best example to understand UITableView is "Contacts List in WhatsApp." Yes, the list of contacts we all see in whatsApp App is created using UITableView.

UITableView consists of number of rows in vertical view and each row is called as cell. Each cell is created in reusable Fashion.

How cells are created using Reusable Fashion ?

Suppose you want to create a list of 1000 contacts in your app using UITableView. Then instead of creating row 1000 times "UItableView" provides a way to reuse the existing rows .How cells are reused to help our app to be efficient ? What is Reuse actually ? Why should we use reuse cells ? All questions will be answered in example below.

Most Used Delegates and DataSource Methods in General

 
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;

-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(nonnull NSIndexPath *)indexPath;

- (void)reloadData;

- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;


UITableView Example

This example explains you to understand the basics of UITableView . Here,we will create a Codzify App which shows the list of titles of tutorials in codzify.com website.

Final Output :-


Open Xcode Goto File > New >Project >Single View Application > Enter Project Name (eg :- FirstProjectViewController) > Done.

Now two files will be created named "ViewController.h"and "ViewController.m"

Now start runnning a program by clicking black forward Button on top of XCode.


You will see blank white screen because we haven't written any code

We start first with AppDelegate.m File. Copy and paste this code in didFinishLaunchingWithOptions method (the very first method you can see in Appdelegate.m)

#import "AppDelegate.h"
#import "ViewController.h"   /* Import this because this is aview Controller which we want to start first. */

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
    ViewController *abcController = [[ViewController alloc]init];
    
    UINavigationController *navController = [[UINavigationController alloc]initWithRootViewController:abcController];
     self.window.rootViewController = navController;
    [self.window makeKeyAndVisible];
    return YES;
}

@end

AppDelegate is the file which is called first when your App Starts . There are many ViewControllers added in your file . So How our App knows which one to start first ? So in didFinishLaunchingApplications we told our code to begin with ViewController file.

UINavigationController is mostly you see in every App. This is an header with blue color as you see in Final Output Image. Word itself tells its mean. It Controls all the navigation .

self.window.rootViewController = navController;

In this way you can set Root View Controller . In our case we want ViewController file to be the first one to start.

ViewController.h file looks like this :-

@interface ViewController () 

@end

ViewController.m file looks like this :-

#import "ViewController.h"
@interface ViewController() <UITableViewDelegate,UITableViewDataSource>
{ 
UITableView *tableViewTutorialsTitle ;
NSArray *titlesArray ;
}
@end
 
@implementation ViewController
 
- (void)viewDidLoad {
    [super viewDidLoad];
   
 /* Change backgroundColor of Navigation Bar */
    NSArray *ver = [[UIDevice currentDevice].systemVersion componentsSeparatedByString:@"."];
    if ([[ver objectAtIndex:0] intValue] >= 7) {
        // iOS 7.0 or later
        self.navigationController.navigationBar.barTintColor = [UIColor colorWithRed:0.0/255.0 green:120.0/255.0 blue:176.0/255.0 alpha:1.0];
        self.navigationController.navigationBar.translucent = NO;
    }else {
        // iOS 6.1 or earlier
        self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:0.0/255.0 green:120.0/255.0 blue:176.0/255.0 alpha:1.0];
    }
    
    /* give title to navigation bar */
    self.navigationItem.title = @"Programming Languages";
    
    /* Change the textColor of navigation bar title */
    [self.navigationController.navigationBar setTitleTextAttributes:
     @{NSForegroundColorAttributeName:[UIColor whiteColor]}];
    
   /* initialise titleArray */
    titlesArray = @[ @"C", @"Objective-C", @"iOS Tutorials",@"Core Java",@"Advanced Java",@"Android Programming",@"Python"];

    /* Allocate tableViewTutorialsTitle here */
   tableViewTutorialsTitle = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
    tableViewTutorialsTitle.delegate = self;
    tableViewTutorialsTitle.dataSource = self;
    [self.view  addSubview:  tableViewTutorialsTitle];
    
}


#pragma mark - Table View Delegates
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return titlesArray.count;
}
 
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cellIdentifier";
    
    UITableViewCell *cell = [tableViewTutorialsTitle dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        
    }
    cell.textLabel.text =  [titlesArray objectAtIndex : indexPath.row];
    return cell;
}
 
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"title of cell %@", [titlesArray objectAtIndex:indexPath.row]);
}
@end

A short description of Example :-

Comments itself are self explanatory. What we did til now is we had given a backgroundColor to NavigationBar , Added a Programming Languages title and given a White text Color to Title .

Here, viewDidLoad() method is called first. In this method , we initialised a UItableView and assigned a frame to it with style UITableViewStylePlain

tableViewTutorialsTitle = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];

Then , we registered a datasource and delegate methods of TableView. We have to register these methods to implement its delegate methods.

tableViewTutorialsTitle.delegate = self;
tableViewTutorialsTitle.dataSource = self;

Last line adds tableViewTutorialsTitle as a subView inside view.

[self.view addSubview: tableViewTutorialsTitle];

In numberOfRowsInSection we are going to use the count of elements in our NSArray to tell the tableView how many rows we are going to be using:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return  titlesArray.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"cellIdentifier";
    
    UITableViewCell *cell = [tableViewTutorialsTitle dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        
    }
    cell.textLabel.text =  [titlesArray objectAtIndex : indexPath.row];
    return cell;
}

cellForRowAtIndexPath is an bread and Butter of TableView. This is a method where all the contents of an array (here, titlesArray) will be shown in a list.

But question comes if we have an array of 1000 elements then should we create 1000 rows ? No . There is a concept introduced in UITableViewCell is Create the number of rows which can be visible on particular screen (say, 10 rows) Then , Question comes, What about other 990 rows? when you scroll the screen then datasource of UITableView tells the internal code written by Apple developers use those 10 cells which were created at first time but please don’t recreate them . We want our App Fast and this becomes possible if we save memory. just change the content inside it (say,Python Tutorials) not the complete cell or row. This is called as reusing the existing cells.

Okay, Its theory. But how can we achieve this in Practical ?

There is a concept called Identifier . Identifier is a just a string (say, "DemoString" or "cellIdentifier" or "anything") Here , in this example its “cellIdentifier”

static NSString *cellIdentifier = @"cellIdentifier";
 UITableViewCell *cell = [tableViewTutorialsTitle dequeueReusableCellWithIdentifier:cellIdentifier];

At first time, dequeueReusableCellWithIdentifier checks wether the cells are available in the queue .Cells are available for first time ? No. So it returns nil.


if(cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        
    }
 

cell returns nil and condition will be satisfied in next statement. So, it allocates UITableViewCell and assign it reuseIdentifier named as cellIdentifier(just any string) so that it can be uniquely identified.

cell.textLabel.text =  [titlesArray objectAtIndex : indexPath.row];

then cells textLabel Property is assigned with titlesArray content. IndexPath is used to find the index of a row. To get the particular row of UITableViewCell you can use indexPath.row and to get the particular section of UITableView use indexPath.section. Now What is Section ? We will cover that in our next tutorial.

Now, when you scroll the screen again cellForRowAtIndexPath method will be called. Then Again dequeueReusableCellWithIdentifier will return a cell. But this time we already have cells in a queue right? So cell == nil condition will becomes false. So there is no need to allocate UITableViewCell again. In this way it saves memory by reusing the cells and uses unique identifier to distinguish the cells for its internal code written by apple developers.