A table view is simply a scrolling view that is separated into
sections, each of which is further separated into rows. Each row is an instance of the UITableViewCell
class, and you can create custom
table view rows by subclassing this class.
Using table views is an ideal way to present a list of items to users. You can embed images, text, and other objects into your table view cells; you can customize their height, shape, grouping, and much more. The simplicity of the structure of table views is what makes them highly customizable.
A table view can be fed with data using a table view data
source, and you can receive various events and control the physical
appearance of table views using a table view delegate object. These are
defined, respectively, in the UITableViewDataSource
and UITableViewDelegate
protocols.
Although an instance of UITableView
subclasses UIScrollView
, table views can only scroll
vertically. This is more a feature than a limitation. In this chapter, we
will discuss the different ways of creating, managing, and customizing
table views.
Table views can be utilized in two ways:
By using the
UITableViewController
class. This class is similar to theUIViewController
class (see Recipe 1.9) in that it is a view controller, but representing a table instead of a normal view. The beauty of this class is that every instance of it already conforms to theUITableViewDelegate
and theUITableViewDataSource
protocols. So the table view controller by default becomes the data source and the delegate of the table view that it controls. Therefore, in order to implement a method of, for instance, the data source of the table view, all you have to do is implement it in the table view controller instead of having to set the data source of your table view manually to your view controller.By instantiating the
UITableView
class manually.
Both these methods are valid methods of creating table views. The first method is usually used when you have a table view that fills its container (or the whole screen/window, if the table view controller is the root view controller of the main window of your app). The second method is usually used for situations where you want to display your table view as a smaller part of your UI, perhaps taking half the width and/or height of the screen. But nothing prevents you from using the second method and setting the width and height of your table view to the width and height of your container window, so that your table view fills the whole screen. We will explore both these methods in this chapter.
Let’s have a look at an example of creating a table view in our application. We are going to see an example of table view controllers in Recipe 4.9, so for now, we will simply focus on creating table views in code and adding them to an existing view controller.
The way to instantiate UITableView
is through its initWithFrame:style:
method. Let’s see what
parameters we have to pass to this method and what those parameters
mean:
initWithFrame
This is a parameter of type
CGRect
. This specifies where the table view has to be positioned in its superview. If you want your table view to simply cover your whole view, pass the value of thebounds
property of your view controller’s view to this parameter.style
This is a parameter of type
UITableViewStyle
that is defined in this way:typedef
NS_ENUM
(
NSInteger
,
UITableViewStyle
)
{
UITableViewStylePlain
,
UITableViewStyleGrouped
};
Figure 4-1 shows the difference between a plain table view and a grouped table view.
We feed data to a table view using its data source, as we will see
in Recipe 4.1. Table views also have delegates that receive various events from
the table view. Delegate objects have to conform to the UITableViewDelegate
protocol. There are some
methods in this protocol that are quite important to know:
tableView:viewForHeaderInSection:
Gets called on the delegate when the table view wants to render the header view of a section. Each section of a table view can contain a header, some cells, and a footer. We will talk about all these in this chapter. The header and footer are simple instances of
UIView
. This method is optional, but if you want to configure a header for your table view sections, use this method to create that instance of the view and return it as the return value. To read more about headers and footers in table views, refer to Recipe 4.5.tableView:viewForFooterInSection:
Same as the
tableView:viewForHeaderInSection:
delegate method, but returns the footer view. Like the header, the footer is optional but should be created here if you want one. To read more about headers and footers in table views, refer to Recipe 4.5.tableView:didEndDisplayingCell:forRowAtIndexPath:
Gets called on your delegate object when a cell is scrolled off the screen. This is a really handy method to have called on our delegate because you can delete objects and remove them from memory, if those objects were associated with the cell that is scrolled off the screen and you expect that you may no longer need them.
tableView:willDisplayCell:forRowAtIndexPath:
This method is called on the delegate of a table view whenever a cell is about to be displayed on the screen.
You can set the delegate of a table view simply by setting the value
of the delegate
property of an instance
of UITableView
to an object that
conforms to the UITableViewDelegate
protocol. If your table view is part of a view controller, you can simply
make your view controller the delegate of your table view, like so:
#import "ViewController.h"
@interface
ViewController
()
<
UITableViewDelegate
>
@property
(
nonatomic
,
strong
)
UITableView
*
myTableView
;
@end
@implementation
ViewController
-
(
void
)
viewDidLoad
{
[
super
viewDidLoad
];
self
.
myTableView
=
[[
UITableView
alloc
]
initWithFrame:
self
.
view
.
bounds
style:
UITableViewStylePlain
];
self
.
myTableView
.
delegate
=
self
;
[
self
.
view
addSubview
:
self
.
myTableView
];
}
@end
Think of the delegate of a table view as an object that listens to various events sent by the table view, such as when a cell is selected or when the table view wants to figure out the height of each of its cells.
Note
It is mandatory for the delegate object to respond to messages
that are marked as @required
by the
UITableViewDelegate
protocol.
Responding to other messages is optional, but the delegate must respond
to any messages you want to affect the table view.
Messages sent to the delegate object of a table view carry a parameter that tells the delegate object which table view has fired that message in its delegate. This is very important to note because you might, under certain circumstances, require more than one table view to be placed on one object (usually a view). Because of this, it is highly recommended that you make your decisions based on which table view has actually sent that specific message to your delegate object, like so:
-
(
CGFloat
)
tableView:
(
UITableView
*
)
tableView
heightForRowAtIndexPath:
(
NSIndexPath
*
)
indexPath
{
if
([
tableView
isEqual
:
self
.
myTableView
]){
return
100.0f
;
}
return
40.0f
;
}
The location of a cell in a table view is represented by its index path. An index path is the combination of the section and the row index, where the section index is the zero-based index specifying which grouping or section each cell belongs to, and the cell index is the zero-based index of that particular cell in its section.
Get iOS 7 Programming Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.