I have a custom UITableViewCell
that I am instantiating from a nib using instantiateWithOwner:(id)owner options:(NSDictionary *)options
. When the nib is instantiated, I am saving it to an IBOutlet defined in my view controller, which is set as the file's owner in the .xib file. Everything's been working great.
I've now come across the need to use this custom cell in multiple view controllers. I was hoping that I could define a protocol (e.g. CustomCellOwner), which multiple view controllers could implement. The protocol would simply define the IBOutlet used to reference the cell when instantiated.
So ideally, I would like to set "file's owner" to:
id <CustomCellOwner>
in Interface Builder.
However, Interface Builder only seems to allow you to set file's owner to a known class, not to an id implementing a protocol?
Is there any way to do this? Or, a simpler way to approach this problem?
Thanks!
I ran into this today and didn't find a good solution. I did however hack it so that it seems to work ok. It definitely feels like a hack though.
First I created a "fakeOwner" class like this:
I then set the object's owner in the XIB as fakeOwner and connected the outlet. Then for each controller that wants to use these cells I add the same property and create the class like this:
Since the fakeOwner and my controller have the same IBOutlet, loading the cell with the controller as the owner causes the connection to happen even though that isn't what is explicitly set in the XIB.
Not 100% if the memory management is right currently (I think it's ok), but other than that it seems to work great. I would love to see a better way of doing this though.
Another option might be to create a lightweight 'factory' object that handles the creation of the cells for you. This object would be the
FilesOwner
in interface builder, with therootObject
outlet set appropriately.Then in the view controllers:
I prefer explicitly setting the root object instead of searching through the array returned from
instantiateWithOwner:options:
because I know the position of the objects in this array has changed in the past.Making a fake owner will work; however, such a solution may be fragile and inextensible. In a sense, the cell owns itself, but even that is technically incorrect. The truth is that
UITableViewCell
s do not have owners.The proper way to implement a custom table view cells is to first create a custom subclass of UITableViewCell. In this class you will define all of the IBOutlets and such for the cell. Here is a sample of a header file:
From there, I have a convenience method that creates the cell from the nib, if necessary:
This method encapsulates all of the creation code so I never have to see it or rewrite it. It assumes that the custom cell is the first root view in the nib. This is a fairly safe assumption since you should only have the custom cell as a root view.
With all this code in place, you are ready to work in Interface Builder. You first need to set the custom class in the identity inspect. Next, don't forget to set your cell identifier. For convenience, it's best to use the name of the custom class. When you drag your connections, rather than drag them to File's Owner, drag your connections to the custom cell itself.
Most of what I have learned about custom table view cells comes from iOS Recipes recipes 15-16. Here is a free extract directly from The Pragmatic Bookshelf. You can check out that book for more details.
EDIT:
I finally got around to open sourcing my
RBSmartTableViewCell
class. You can find it on my GitHub. You should find this class more useful than the code directly from iOS Recipes, since my class treats all cells the same, regardless of whether they are constructed using XIBs, UIStoryboard, or code. This repo also includes working samples.This isn't the solution you're asking for, but you could make a
UIViewController
subclass that you subclass for each view controller that needs to use your nib. Something like:And then use that as the base class for each:
Then you could simply set
File's Owner
toCustomCellOwnerViewController
with no problems.Just an idea.
In iOS 5.0 there is now the
registerNib:forCellReuseIdentifier:
method onUITableView
which I believe attempts to solve a similar problem.From the documentation:
This could be an alternative approach depending on your requirements.