I recently found myself complaining about the many ways that UITableViewController falls short for the hundredth time. It is fine if you are only concerned with displaying a single table, but adding any other controls becomes difficult. There are also a few bugs with UITableView that require additional views to work around, so it’s common to add more views even if you are using a very simple table. There is a very clear workaround for all of these things, which is to use UIViewController and implement the UITableViewDataSource and UITableViewDelegate protocols yourself. There is an Xcode File Template for a UITableViewController that stubs in all of these methods for you, which is super useful. I wanted to create a template with the same stubs but with the UIViewController+UITableViewDataSource/UITableViewDelegate pattern.
The basics of doing this are simple enough. Copy the “UITableViewController subclass with XIB.pbfiletemplate” folder from
/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/File Templates/Cocoa Touch Class/
to somewhere you want to edit it, then edit the class.m and class.h files until they look like what you want. In our case we added a few things and removed a few things from the .m, and made the appropriate class changes in the .h. Copy the resulting folder into
~/Library/Application Support/Developer/Shared/Xcode/File Templates/Cocoa Touch Class/
(you may have to create some of those folders) and it’ll appear in the source list in Xcode.
However, I wanted to get a bit fancier. Shouldn’t my template come with a XIB already prewired with outlets from my controller to a view and tableview, as well as delegate/datasource connections from the tableview to the controller? Seems like the point of having the template is to be able to write code as soon as possible, so I decided I’d hook up the XIB beforehand.

The first step is to rename the view.xib.preprocessed file to view.xib, so that we can open it in Interface Builder. I added a UITableView as a subclass of the main view. The main view is already connected to File’s Owner’s view property, exactly as we want. We want to connect the tableview to the tableView outlet of our new class. It seems that Interface Builder isn’t able to decipher the template class.h to figure out that our class has this outlet though. I thought I was out of luck, but then I remembered that the X in XIB stands for XML (or at least I think it does!).
Open the XIB in your favorite text editor and you’ll see (fairly) straightforward XML. Search for the line
<object class="NSMutableArray" key="connectionRecords">.
This array contains all of the connections set up in IB. We want to add 3 connections, so head to the bottom of this array (line before <object class="IBMutableOrderedSet" key="objectRecords">). Our connections look like
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">mTableView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="873029372"/>
</object>
<int key="connectionID">11</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">dataSource</string>
<reference key="source" ref="873029372"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">12</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">delegate</string>
<reference key="source" ref="873029372"/>
<reference key="destination" ref="372490531"/>
</object>
<int key="connectionID">13</int>
</object>
The “ref=” parts refer to the objects defined in the (<object class="IBMutableOrderedSet" key="objectRecords">) section. Each object is given a unique ID. In our case we want the ref of “File’s Owner” (372490531 for us). The ref of our TableView is 873029372. Your values may differ. The one tricky thing here is that the connectionID must be unique (I think) so look above and make sure you haven’t duplicated any of them. If you have, just start counting at the next number. I thought I would be good to go at this point, but if you try to use this template and then build the project you will get a warning (an error if you’re treating warnings as errors as you should) about the outlet being connected but no longer defined in your controller. The reason for this is a bit further in the XML file. Search for the line
<string key="className">«FILEBASENAMEASIDENTIFIER»</string>
This is in the middle of the definition for your new controller class. Add the following lines (under the “superClassName” line, though it shouldn’t matter).
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">mTableView</string>
<string key="NS.object.0">UITableView</string>
</object>
What does this mean? It is a dictionary mapping outlet names to type. So NS.key.X maps to type of NS.object.X. In our case we just have the one outlet to define so it's just the two lines.
With that complete, save the XIB, and rename it to view.xib.unpreprocessed. You can now edit the TemplateInfo.plist file to give your template a decent description.

Your file template is ready to go, just drop it in
~/Library/Application Support/Developer/Shared/Xcode/File Templates/Cocoa Touch Class/
and get back to coding.
0 Comments