Stanford CS193p: Developing Applications For iOS Spring 2016
Stanford CS193p: Developing Applications For iOS Spring 2016
CS193p
Spring 2016
Today
Table View
Way to display large data sets
Demo: Twitter Client
CS193p
Spring 2016
UITableView
UITableViewStyle.Plain .Grouped
Dynamic (List)
Static
& Plain
& Grouped
(ungrouped)
CS193p
Spring 2016
UITableView
Plain Style
Table Header
Spring 2016
UITableView
Plain Style
Table Header
Table Footer
Spring 2016
UITableView
Plain Style
Table Header
Section
Table Footer
CS193p
Spring 2016
UITableView
Plain Style
Table Header
Section Header
Section
Table Footer
Spring 2016
UITableView
Plain Style
Table Header
Section Header
Section Footer
Section
Table Footer
Spring 2016
UITableView
Plain Style
Table Header
Section Header
Table Cell
Section Footer
Section
Table Footer
Spring 2016
UITableView
Plain Style
Table Header
Section Header
Table Cell
Section Footer
Section
Table Footer
CS193p
Spring 2016
UITableView
Grouped Style
Table Header
Section Header
Table Cell
Section Footer
Section
Table Footer
CS193p
Spring 2016
Sections or Not
No Sections Sections
CS193p
Spring 2016
Cell Type
Spring 2016
The class UITableViewController
provides a convenient packaging of a
UITableView in an MVC.
Spring 2016
Controller: (subclass of) UITableViewController
CS193p
Spring 2016
Like any other View Controller,
CS193p
Spring 2016
Just use
CS193p
Spring 2016
… otherwise it won’t
make sense to set it as
the class here.
CS193p
Spring 2016
Your UITableViewController subclass
will also serve as the
If you use UITableView without UITableViewController, you’ll have to wire these up yourself.
CS193p
Spring 2016
You can edit
attributes of the
UITableView by
inspecting it.
(or ctrl-shift-left-click)
CS193p
Spring 2016
One important attribute is the
Plain vs. Grouped style …
CS193p
Spring 2016
CS193p
Spring 2016
Grouped
CS193p
Spring 2016
Grouped
CS193p
Spring 2016
Grouped
CS193p
Spring 2016
A more interesting table,
however, is a Dynamic one …
Grouped
CS193p
Spring 2016
Grouped
… which we almost
always use in Plain style.
CS193p
Spring 2016
These cells are now templates which will be
repeated for however many rows are needed to
display the data in MVC’s Model.
CS193p
Spring 2016
Any cell can be inspected
CS193p
Spring 2016
Subtitle cell style
CS193p
Spring 2016
You can also set a
symbol to appear on the
right of the cell.
CS193p
Spring 2016
We’ll talk about this Detail Disclosure button in a bit.
CS193p
Spring 2016
CS193p
Spring 2016
CS193p
Spring 2016
One of the
cell styles you
can choose is
Custom.
CS193p
Spring 2016
Like the cells in a static table view,
CS193p
Spring 2016
You can change their size.
CS193p
Spring 2016
And you can drag UI
elements into them.
CS193p
Spring 2016
It is important to set proper autolayout
constraints if you want your Custom cells to adjust
their height automatically to their content.
CS193p
Spring 2016
CS193p
Spring 2016
CS193p
Spring 2016
To wire up any outlets, though, you have to
create a custom subclass of the class of UIView
that is in these cells: UITableViewCell.
CS193p
Spring 2016
You create a custom subclass of
UITableViewCell just like any other
subclass. Using File -> New File …
CS193p
Spring 2016
CS193p
Spring 2016
Choose UITableViewCell as
the class to subclass off of.
CS193p
Spring 2016
Then set it in the Identity
Inspector as usual.
CS193p
Spring 2016
Now you can wire up UI outlets and
actions to the UI elements in the cell.
CS193p
Spring 2016
Just open up your
CS193p
Spring 2016
Remember that this is a “prototype” cell, so
there will be an instance of this cell for every
visible row (each with its own UI and outlets).
CS193p
Spring 2016
UITableView Protocols
How to connect all this stuff up in code?
Connections to code are made using the UITableView‘s dataSource and delegate
The delegate is used to control how the table is displayed (it’s look and feel)
The dataSource provides the data that is displayed inside the cells
Spring 2016
Customizing Each Row
Providing a UIView to draw each row …
It has to be a UITableViewCell (which is a subclass of UIView) or subclass thereof
Don’t worry, if you have 10,000 rows, only the visible ones will have a UITableViewCell
But this means that UITableViewCells are reused as rows appear and disappear
This has ramifications for multithreaded situations, so be careful in that scenario
The UITableView will ask its UITableViewDataSource for the UITableViewCell for a row …
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
CS193p
Spring 2016
Customizing Each Row
Providing a UIView to draw each row …
It has to be a UITableViewCell (which is a subclass of UIView) or subclass thereof
Don’t worry, if you have 10,000 rows, only the visible ones will have a UITableViewCell
But this means that UITableViewCells are reused as rows appear and disappear
This has ramifications for multithreaded situations, so be careful in that scenario
The UITableView will ask its UITableViewDataSource for the UITableViewCell for a row …
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let data = myInternalDataStructure[indexPath.section][indexPath.row]
CS193p
Spring 2016
Customizing Each Row
Providing a UIView to draw each row …
It has to be a UITableViewCell (which is a subclass of UIView) or subclass thereof
Don’t worry, if you have 10,000 rows, only the visible ones will have a UITableViewCell
But this means that UITableViewCells are reused as rows appear and disappear
This has ramifications for multithreaded situations, so be careful in that scenario
The UITableView will ask its UITableViewDataSource for the UITableViewCell for a row …
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let data = myInternalDataStructure[indexPath.section][indexPath.row]
return cell
}
CS193p
Spring 2016
Customizing Each Row
Providing a UIView to draw each row …
It has to be a UITableViewCell (which is a subclass of UIView) or subclass thereof
Don’t worry, if you have 10,000 rows, only the visible ones will have a UITableViewCell
But this means that UITableViewCells are reused as rows appear and disappear
This has ramifications for multithreaded situations, so be careful in that scenario
The UITableView will ask its UITableViewDataSource for the UITableViewCell for a row …
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let data = myInternalDataStructure[indexPath.section][indexPath.row]
return cell
}
}
CS193p
Spring 2016
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let data = myInternalDataStructure[indexPath.section][indexPath.row]
CS193p
Spring 2016
func tableView(tv: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let data = myInternalDataStructure[indexPath.section][indexPath.row]
}
CS193p
Spring 2016
This method gets a UITableViewCell for
us either by reusing one that has gone off
screen or by making a copy of one of our
prototypes in the storyboard.
}
CS193p
Spring 2016
For a non-Custom cell …
dequeued.textLabel?.text = data.importantInfo
dequeued.detailTextLabel?.text = data.lessImportantInfo
return cell
}
CS193p
Spring 2016
For a Custom cell …
return cell
}
CS193p
Spring 2016
… the dequeued thing will be your subclass of UITableViewCell.
(i.e. that public API will set the values of its outlets, etc.).
Spring 2016
UITableViewDataSource
How does a dynamic table know how many rows there are?
And how many sections, too, of course?
Via these UITableViewDataSource protocol methods …
func numberOfSectionsInTableView(sender: UITableView) -> Int
func tableView(sender: UITableView, numberOfRowsInSection: Int) -> Int
CS193p
Spring 2016
UITableViewDataSource
Summary
Loading your table view with data is simple …
1. set the table view’s dataSource to your Controller (automatic with UITableViewController)
2. implement numberOfSectionsInTableView and numberOfRowsInSection
3. implement cellForRowAtIndexPath to return loaded-up UITableViewCells
CS193p
Spring 2016
How do you segue when a row is touched?
Just ctrl-drag from a prototype (or static) row to another MVC of course …
CS193p
Spring 2016
You can choose from any of
the segues you are used to.
CS193p
Spring 2016
If you have a Detail Disclosure Accessory,
CS193p
Spring 2016
Just set the identifier as usual.
prepareForSegue
CS193p
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
default: break
}
}
}
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
}
default: break
}
}
}
So you will need to cast sender with as? to turn it into a UITableViewCell
If you have a custom UITableViewCell subclass, you can cast it to that if it matters
CS193p
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
}
default: break
}
}
}
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
}
default: break
}
}
}
Now we just get our destination MVC as the proper class as usual …
CS193p
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
and then get data from our internal data structure using the NSIndexPath’s section and row
CS193p
Spring 2016
Table View Segues
Preparing to segue from a row in a table view
and then get data from our internal data structure using the NSIndexPath’s section and row
and use that information to prepare the segued-to API using its public API
CS193p
Spring 2016
UITableViewDelegate
So far we’ve only talked about the UITableView’s dataSource
But UITableView has another protocol-driven delegate called its delegate
The delegate also lets you observe what the table view is doing
Especially responding to when the user selects a row
Usually you will just segue when this happens, but if you want to track it directly …
CS193p
Spring 2016
UITableView “Target/Action”
UITableViewDelegate method sent when row is selected
This is sort of like “table view target/action” (only needed if you’re not segueing, of course)
Example: if the master in a split view wants to update the detail without segueing to a new one
func tableView(sender: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
// go do something based on information about my Model
// corresponding to indexPath.row in indexPath.section
// maybe directly update the Detail if I’m the Master in a split view?
}
CS193p
Spring 2016
UITableViewDelegate
Lots and lots of other delegate methods
will/did methods for both selecting and deselecting rows
Providing UIView objects to draw section headers and footers
Handling editing rows (moving them around with touch gestures)
willBegin/didEnd notifications for editing
Copying/pasting rows
CS193p
Spring 2016
UITableView
What if your Model changes?
func reloadData()
Causes the UITableView to call numberOfSectionsInTableView and numberOfRowsInSection
all over again and then cellForRowAtIndexPath on each visible row
Relatively heavyweight, but if your entire data structure changes, that’s what you need
If only part of your Model changes, there are lighter-weight reloaders, for example ...
func reloadRowsAtIndexPaths(indexPaths: [NSIndexPath],
withRowAnimation: UITableViewRowAnimation)
CS193p
Spring 2016
UITableView
Controlling the height of rows
Row height can be fixed (UITableView’s var rowHeight: CGFloat)
Or it can be determined using autolayout (rowHeight = UITableViewAutomaticDimension)
If you do automatic, help the table view out by setting estimatedRowHeight to something
The UITableView’s delegate can also control row heights …
func tableView(UITableView, {estimated}heightForRowAtIndexPath: NSIndexPath) -> CGFloat
Beware: the non-estimated version of this could get called A LOT if you have a big table
CS193p
Spring 2016
UITableView
There are dozens of other methods in UITableView itself
Setting headers and footers for the entire table.
Controlling the look (separator style and color, default row height, etc.).
Getting cell information (cell for index path, index path for cell, visible cells, etc.).
Scrolling to a row.
Selection management (allows multiple selection, getting the selected row, etc.).
Moving, inserting and deleting rows, etc.
As always, part of learning the material in this course is studying the documentation
CS193p
Spring 2016