I'm trying to make use of the new Storyboard designer and the ease of drawing UITableView cells instead of programmatically "designing" each row.
A good example of a standard cell is linked here at stack overflow: iPhone - dequeueReusableCellWithIdentifier usage
Instead of the linked approach of using "[cell textLabel]" I want to use my own labels, buttons and images on top of each row. Therefore I created several prototype cells/rows and assigned identifiers to them (using Storyboard).
Now: what is the smartest way of accessing each row's "custom" controls/labels? I tried searching for accessing them by ID, but didn't find anything. My thinking was it should work along this lines:
[[[cell subviews] getObjectByID:@"labelTime"] setText:@"Whatever"];
Is my expectation of the APIs completely wrong or didn't I just find the right API, yet?
Any ideas or recommendations?
A prototype cell acts a template for your cell's appearance. It includes the views you want to display and their arrangement within the content area of the cell. At runtime, the table's data source object creates actual cells from the prototypes and configures them with your app's data.
A view that presents data using rows in a single column. iOS 2.0+ iPadOS 2.0+ Mac Catalyst 13.1+ tvOS 9.0+
For each new custom UITableViewCell that you create in storyboard, you will want to create a new class file which implements UITableViewCell to link it to. Be sure to map all of the controls within your new cell that you laid out in storyboard to instance properties. Then you'll just use it with dequeuing like normal:
YourTableViewCellClass *cell = (YourTableViewCellClass*)[tableView dequeueReusableCellWithIdentifier:@"YourCellIdentifierStringDefinedInStoryBoard"];
// then set the properties for the class.
cell.labelTime = @"whatever";
There are two ways you can get to your custom subviews. The simpler way is using tags. Every view has a tag
property which is an integer. You can set the tag in the nib, and set or get it in code. You can search a view tree for a view with a given tag by sending viewWithTag:
to the root of the tree. So, for example, you could give your labelTime
view the tag 57, and in your code, you'd find the view like this:
UILabel *label = (UILabel *)[cell viewWithTag:57];
The downside of using tags is that you have to keep the tag numbers in sync between your nib and your code. If they get out of sync, you'll either get the wrong view back or you'll get nil (and since you can send messages to nil, the system won't give you an error when that happens). Still, tags are so convenient that it's pretty common to use them like this.
The other way is to create a custom subclass of UITableViewCell
with an IBOutlet
property for each custom subview. You can hook up the outlets to the subviews in the nib, and access the subviews via the properties in your code:
MyTableViewCell *myCell = (MyTableViewCell *)cell;
UILabel *label = cell.labelTime;
This entails writing a lot more boilerplate than using tags, but it has the advantage that you will get warnings or errors (either at compile-time or when you first try to load the nib) if your nib and your code get out of sync.
Don't be a doofus like I was being. :)
Make sure you set the Identifier value in the Attributes Inspector of the custom cell. Setting the Restoration ID of the custom cell in the Identity Inspector is the wrong way to go, and that's exactly what I did. Major facepalm for myself.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With