• No results found

GoalKicker.com – iOS® Developer Notes for Professionals 98 }

heightForHeaderInSection: and heightForFooterInSection Define the height for the header and footer of each section in the table view

Objective-C

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

} Swift 3

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return 33

}

In this example, we'll just set an array with some strings (text) as our data source:

Swift

let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

Objective-C

// You'll need to define this variable as a global variable (like an @property) so that you can access it later when needed.

NSArray *myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];

Setting up your data source in your View Controller

Make sure your view controller conforms to the UITableViewDataSource protocol.

Swift

class ViewController: UIViewController, UITableViewDataSource { Objective-C

@interface ViewController : UIViewController <UITableViewDataSource>

As soon as your view controller has declared it will conform to the UITableViewDataSource (that's what we've just done above), you are required to implement at least the following methods in your view controller class:

tableView:numberOfRowsInSection, this asks you how many rows your table view should have.

// Swift

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.myDataArray.count

}

tableView:cellForRowAtIndexPath, requests that you create and return a cell for each row you specified in tableView:numberOfRowsInSection. So, if you said you needed 10 rows, this method will be called ten times for each row, and you need to create a cell for each of those rows.

// Swift

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->

UITableViewCell {

// Create a new cell here. The cellReuseIdentifier needs to match the reuse identifier from the cell in your Storyboard

let cell: UITableViewCell =

tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!

// Set the label on your cell to the text from your data array cell.textLabel?.text = self.myDataArray[indexPath.row]

return cell }

GoalKicker.com – iOS® Developer Notes for Professionals 100 WARNING: You may NOT return nil for any cells in cellForRowAtIndexPath:. This will cause your app to crash, and you will see the following error in the console:

Uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

Connecting the table view's data source to your view controller

You can either do this via code by setting your table's dataSource property to self on your view controller. Or you may select your table view in your storyboard, open the Attributes Inspector, select the "Outlets" panel, and drag from dataSource to your view controller (NOTE: make sure you connect to the UIViewCONTROLLER, not a UIView or another object in your UIViewController).

Handling row selections

When a user taps on a row in your table view, generally, you'll want to do something - to respond. In many apps, when you tap on a row, more information about that item you tapped upon is displayed. Think of the Messages app: when you tap on the row showing one of your contacts, the conversation with that person is then displayed on screen.

In orer to do that, you must conform to the UITableViewDelegate protocol. Doing so is similar to conforming to the data source protocol. This time however, you'll just add it next to UITableViewDataSource and separate it with a comma. So it should look like this:

Swift

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { Objective-C

@interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>

There are no required methods to implement for the table view's delegate. However, to handle row selections you'll need to use the following method:

tableView:didSelectRowAtIndexPath, this is called whenever a row is tapped, which allows you to do something in response. For our example, we'll just print a confirmation statement to the Xcode log.

// Swift

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { print("You tapped cell number \(indexPath.row).")

}

// Objective-C

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSLog(@"You tapped cell number %ld.", (long)indexPath.row);

}

The Final Solution

See below for the full setup with just code, no explanation.

Swift

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

// Data model: These strings will be the data for the table view cells

let myDataArray: [String] = ["Row one", "Row two", "Row three", "Row four", "Row five"]

// cell reuse id (cells that scroll out of view can be reused) let cellReuseIdentifier = "cell"

// don't forget to hook this up from the storyboard @IBOutlet var myTableView: UITableView!

override func viewDidLoad() { super.viewDidLoad()

// Register the table view cell class and its reuse id

myTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier:

cellReuseIdentifier)

// This view controller itself will provide the delegate methods and row data for the table view.

myTableView.delegate = self myTableView.dataSource = self }

// number of rows in table view

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return self.myDataArray.count

}

// create a cell for each table view row

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->

UITableViewCell {

// create a new cell if needed or reuse an old one

let cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellReuseIdentifier) as UITableViewCell!

// set the text from the data model

cell.textLabel?.text = self.myDataArray[indexPath.row]

return cell }

// method to run when table view cell is tapped

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { print("You tapped cell number \(indexPath.row).")

} }

Objective-C ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> { IBOutlet UITableView *myTableView;

NSArray *myDataArray;

}

GoalKicker.com – iOS® Developer Notes for Professionals 102

@end

ViewController.m

#import "ViewController.h"

// cell reuse id (cells that scroll out of view can be reused) NSString * _Nonnull cellReuseIdentifier = @"cell";

@implementation ViewController - (void)viewDidLoad {

[super viewDidLoad];

// Data model: These strings will be the data for the table view cells

myDataArray = @[@"Row one", @"Row two", @"Row three", @"Row four", @"Row five"];

// Register the table view cell class and its reuse id

[myTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:cellReuseIdentifier];

// This view controller itself will provide the delegate methods and row data for the table view.

myTableView.delegate = self;

myTableView.dataSource = self;

}

// number of rows in table view

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return myDataArray.count;

}

// create a cell for each table view row

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

*)indexPath {

// create a new cell if needed or reuse an old one

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellReuseIdentifier];

// set the text from the data model

cell.textLabel.text = myDataArray[indexPath.row];

return cell;

}

// method to run when table view cell is tapped

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

NSLog(@"You tapped cell number %ld.", (long)indexPath.row);

}

@end

Related documents