Beginning iOS Development

Course No. 10-152-143

Chapter 9 — UITableView and UITableViewController (iOS)

Examples

The table view is the most important iOS UI element. You see it everywhere.

Here are some examples on an iPhone.


And some on an iPad.

  • They can be customized heavily or the default design can be used.

Beginning the Homepwner Application

  • Create a new Empty Application project for iOS named Homepwner. We’ll be working on this app for several weeks.

UITableViewController

  • A Table View uses two delegates. Two?
  • Yes, two. A Table View has two completely different issues that it has to resolve.
    • Data
    • Display and interaction with the user.


  • When using the delegate pattern, the class will ask its delegate for information when it needs it. We create a delegate object and assign it to the delegate property. Then we implement the delegate methods.
  • Because there are two different delegates for a Table View we use a different name for each. These are the property names.
    • dataSource
    • delegate
  • The Data Source is about the data. What should the table view display? When a table view is scrolled it needs to know what to show in the new cells.
  • The Delegate is about the user interface. It is concerned with how to show the data. It doesn’t know anything about the data, but it knows about the size of the cell, how to edit the cell, what to do when a cell has been deleted or added, and what to do when it is tapped or scrolled.
  • These two delegates can be any object we want, but we usually use the Table View Controller that is controlling our table view as both.

Subclassing UITableViewController

  • Create a new class named ItemsViewController. Have it subclass NSObject when you create it. Then change its superclass to UITableViewController.
  • Add an init method like this.
  • We also need to implement the designated initializer.
  • Open the HomepwnerAppDelegate.m file and import the ItemsViewController class.
  • Add an instance of our view controller and make it the rootViewController.
  • Run the app in the simulator. Not very exciting yet. We haven’t told it about either of its delegates yet so it can’t create any cells or show us any data.


  • We didn’t cover chapter 3 this semester. We need the class BNRItem from that chapter for this project. Download these two files, place them wherever you’d like.
  • Drag them into your project.


  • Check both checkboxes!


  • Open the BNRItem.h and BNRItem.m files and take a look at the code. Does it all make sense?

UITableView’s Data Source

  • We are going to make the Model part of this application more robust. We’re going to make a class to serve all our data. This is a good practice and one we’ll do in the future most of the time.

Creating BNRItemStore

  • Create a new class that subclasses NSObject. Name it BNRItemStore. This class will be a singleton. A singleton means that only one instance of the class can ever be made in an application.
  • Add a declaration for this class method in BNRItemStore.h.
  • There is a new and better way to create a singleton object. The book’s method will work, but the new way is easier to code and works in all circumstances. This new way is generally accepted as the best method for this. Implement the method in BNRItemStore.m like this instead of the book’s code.
    • If you would like to read more about this then here is a link to a post about this topic from a recognized expert.
    • You do not need to implement the allocWithZone: method from the book.
  • Add the highlighted property to the BNRItemStore.h file.
  • Add a class extension to the .m file and add this redeclared property.
    • This property demonstrates a feature of class extensions. The declaration of allItems in the .h file is readonly. Code outside of this class can only read the property. By redeclaring the property in the .m file we can make it readwrite for use inside the class.
  • Now add a forward class directive and a method declaration to the file. They are highlighted here.
    • It is not a good practice to #import the same file in both the .h and .m files of a class. However, we have BNRItem in this file and it won’t compile unless we refer to it somehow. The code @class BNRItem; is a forward declaration. It just tells the compiler that the class is imported somewhere else and don’t worry about resolving it now. It is much lighter weight than an import.
  • Switch to the BNRItemStore.m file and import BNRItem.h.
  • Implement the init method as follows.
    • Remember that we have to use the direct pointer to our property, _allItems inside init methods. Everywhere else we will use the property, self.allItems.
  • Implement the createItem method this way.

Implementing data source methods

  • Now we switch to the view controller.
  • First, import the model classes in ItemsViewController.m.
  • Next, add this highlighted code to the init method to get some items in the model.
  • Now on to the delegates! The view controller itself will be both the dataSource and the delegate. In our case conforming to the protocols was already done in the superclass UITableViewController. We just have to implement the methods.
  • First, we’ll look at how this table view will get it’s data. The protocol for this is named UITableViewDataSource. Here’s what it looks like in the docs.

UITableViewDataSource Protocol Reference

  • Tasks
  • Configuring a Table View
    • – tableView:cellForRowAtIndexPath: required method
    • – numberOfSectionsInTableView:
    • – tableView:numberOfRowsInSection: required method
    • – sectionIndexTitlesForTableView:
    • – tableView:sectionForSectionIndexTitle:atIndex:
    • – tableView:titleForHeaderInSection:
    • – tableView:titleForFooterInSection:
  • Inserting or Deleting Table Rows
    • – tableView:commitEditingStyle:forRowAtIndexPath:
    • – tableView:canEditRowAtIndexPath:
  • Reordering Table Rows
    • – tableView:canMoveRowAtIndexPath:
    • – tableView:moveRowAtIndexPath:toIndexPath:
  • We’ll implement the required methods first. Add this method to the ItemsViewController.m file.
    • This method gets the NSMutableArray of items and returns the count.

UITableViewCells

  • A table view cell is an object that displays one piece of data in a table view.
  • Each cell has several views inside of it to display different parts of the cell.


  • Table cells can be configured many different ways with the built-in default values.


Creating and retrieving UITableViewCells

  • To set the text of each cell we need to implement another method from the UITableViewDataSource protocol, tableView:cellForRowAtIndexPath:.
  • This message gets sent to your dataSource every time a cell is about to be displayed. Implement the following method in ItemsViewController.m.
  • Run it! If everything is correct you should see something like this.


  • Cool!

Reusing UITableViewCells

  • We just made 5 BNRItem instances. What if there were thousands? Tens of thousands?
  • Our iOS apps would crash with out of memory errors long before we got to thousands. Yet we all know we can scroll through long lists of items in a table view without any problem. How do they do that?
  • It works because the UITableView is a treadmill.


  • You need enough UITableViewCells in memory to fill the screen, plus a few more to make scrolling smooth.
  • As cells go offscreen they are reloaded with new data and put right back on screen at the other end of the table view. Here’s a cell scrolling off the bottom of the screen.


  • And it makes its reappearance!


  • To make this happen we need to change some code. Change the tableView:cellForRowAtIndexPath: method to this.
  • The key is the this message.

Code Snippet Library

  • How does this happen?


  • Code Snippets!


  • This is a list of all the code snippets that come with Xcode.
  • Enter “init” in the search bar at the bottom of the window. Click on the snippet labelled Objective-C init Method. The snippet editing dialog opens to the left.


  • Click on the Edit button and you will see this.


  • The greyed-out text means that we can’t edit those fields. However, those are text fields. Does that mean that we can edit these sometimes? Yes!
  • You can add your own snippets. Open an Xcode project. Copy and paste the following code somewhere in a method in your code.
  • Select the text and drag it over to the Code Snippet window.


  • Add a Title and a Completion Shortcut and click on Done. The shortcut should be something very short and easy to remember. I used “linelog” that means “log method and line number” to me.


  • Now go to a different place in your code inside a different method. Type the shortcut and you should see your snippet appear in a popup window.


  • Just press the Enter key and there’s the fancy log line.
  • What does it do? This.
  • It shows you the method or function and its line number. Handy!
  • Some snippets do this when you use them.


  • That’s a special code that allows you to tab and edit very quickly. We can add those to our code, too! Here’s what that looks like in the snippet editor.
  • All we have to do is surround a description with these.
    • <#...#>

Handy Snippets

Here are some snippets that have been handy to many.

  • A method that returns a random UIColor. Suggested code: rc
  • A useful printf. Suggested code pf
  • An else if when you need one. Suggested code: eli
  • A snippet for the tableView:numberOfRowsInSection: method. Suggested codes: tablerows or trows
  • A snippet for the randomNumberFrom:to: Suggested code: randomto