I've been studying Storyboards and the things they let you do. Specifically, I wanted to learn how to set up static table views. Static table views don't require a data source. However, a static table view must be managed by a UITableViewController.
The downside of that is that a UITableViewController is set up so it's content view is its table view. You really can't make a UITableViewController manage a complex set of views where a table view is only a part.
I therefore set myself the challenge of making a view controller that managed 2 different static table views, and got notified when the user selected a cell in either table view.
With iOS 6 this is easy. There is a new user interface object called a container view. You drag a container view onto a view controller and it becomes a container that hosts the contents of another view controller. You then right-click-and-drag from the container view to another view controller and tell IB (Interface Builder) you want to create an embed segue, and it does all the housekeeping for you. (Thanks to GHuebner for showing me how to do this.)
So, if you're willing to use iOS 6 or later, it's actually pretty easy to include one or more static table views in your UI design.
The screen from the app looks like this:
There is a working project on github
(link) that you can clone, or just download for read-only access.
Here is a description of what the project and a very rough outline of how you do it:
Static table view demo project.
Requires iOS 6.0
This project demonstrates several things. It is based on Storyboards, which requires iOS 5.0. It also uses the new embed segue which was added in iOS 6.
1. Using the automatic view controller containment supported with storyboards under iOS 6.0.
Steps to enclose a view controller in another view controller:
a) Display the objects library in the utilities area,
b) Type "container" into the filter bar.
c) Copy a container view onto your view controller.
d) Create a second view controller scene in your storyboard (a table view controller, for this project.)
e) Right-drag/control drag from your container view to your new view controller, and select "embed". This creates an embed segue, which tells the system to set up the "contained" view controller as a child of the containing view controller.
2. Using static table views (Must be managed by a UITableViewController.)
a) Define a custom subclass of UITableViewController in your project. (Let's call it MyTableViewController.)
b) Create a UITableViewController in your storyboard.
c) Go to the identity inspector and switch the class of your table view controller to your custom class.
d) Select the table view inside the new table view controller and select the attributes inspector.
e) Switch the content type to "Static cells"
f) Set up the cells in your table view as desired. (Use custom cell type)
g) If needed, control-drag from the fields of your cells into the header of your table view controller to create outlets and/or actions.
3. Creating links between your parent and child view controller
Saving a link to the child view controller:
a) Click on the embed segue and give it a unique identifier
b) Implement a prepareForSegue method in your parent view controller.
c) In that prepareForSegue method, string match the segue identifier (using the NSString isEqualToString method) and for the desired embed segue, save the destination view controller
4. Setting up the parent view controller as a delegate of the child view controller:
a) Define a protocol for the parent view controller.
b) Add a delegate property in the child view controller that conforms to the parent view controller protocol.
c) Add code to the prepareForSegue method that sets the delegate property of the destination view controller
5. Making taps in table view cells select/deselect the cell:
a) Implement table view tableView:willSelectRowAtIndexPath: and tableView:didSelectRowAtIndexPath: methods.
b) Add logic to toggle selected state of cell if it was selected previously.
6. Passing cell selected actions to parent view controller through delegate property:
a) Add a method to the StaticTableParentProtocol to notify the delegate when the user selects/deselects a cell.
b) Update MyTableViewController's tableView:didSelectRowAtIndexPath method to see if delegate responds to new method, and send message if it does.
7. Construct and display localized message in parent view controller as the user selects/deselects cells in each table view
a) Implement new StaticTableParentProtocol method in parent view controller to display message when user selects/deselects a cell.
b) Use NSLocalizedString for all string constants to localize strings for display.
8. Add buttons to static table view cells
a) Make sure cells are custom type
b) drag a round rect button onto a cell
c) Add a text label (since the custom cell does not have a text label by default.)
d) Make the button shorter to fit inside the table view cell.
e) Duplicate the custom cell with button as many times as needed
f) Put sequential numbered tags on the buttons for each cell, 1..n
g) Create a "cellButtonTapped" IBAction method in the custom table view
h) Link each button's touch up inside action to the cellButtonTapped method.
9. Update MyTableViewController to send a message to parent view controller when user presses buttons on cells, and use add code in MyTableViewController to display a localized message telling the user which button was clicked, and in which table view.
a) Design a new method tableView:clickedButton:withTag:inViewController: in StaticTableParentProtocol to notify parent when user taps a button.
b) Update MyTableViewController's cellButtonTapped method to check delegate to see if it responds to tableView:clickedButton:withTag:inViewController: method, and send the message if it does
c) Implement tableView:clickedButton:withTag:inViewController: method in parent view controller. Make the method construct a localized message about which button tag was clicked, and in which view controller.
10. Add a rounded-corner, colored border around the table views:
a) Add CALayer category with a method setBorderUIColor that takes a UIColor as input and sets the layer's border color with that UIColor's CGColor.
b) Add "User Defined Runtime Attributes" to container views with key/value pairs
The "User Defined Runtime Attributes" look like this: