1

How do I access UITableViewController parameter from within a subclass'ed UITableViewCell?

I have a parameter in the UITableViewController for the font size (i.e. users can change font size). So the layoutSubviews method in my custom subclassed UITableViewCell will need to access the latest font when it needs to re-layout itself (as it label positions will depend on the font).

So my question, from with my custom subclassed UITableViewCell, and specifically within the layoutSubviews method, how do I access the "uiFont" parameter which is an instance variable from the UITableViewController?

Lorenzo B
  • 33,216
  • 24
  • 116
  • 190
Greg
  • 34,042
  • 79
  • 253
  • 454

2 Answers2

4

There are a few ways to do it: access the UITableViewController via a property on the application delegate (which you can access from anywhere using [UIApplication sharedApplication].delegate), give the cell a reference to the UITableViewController when you create it in tableView:cellForRowAtIndexPath:, or follow the UIResponder chain from the cell view until you find a UITableViewController.

But really, this is probably a poor architecture. You should probably just call reloadData on the table view to have it recreate all the cells, and set the font in tableView:cellForRowAtIndexPath:. Or if the font setting should persist, you could store it in NSUserDefaults and have the cells listen for NSUserDefaultsDidChangeNotification.

Anomie
  • 92,546
  • 13
  • 126
  • 145
  • I was wondering about the reloadData call & thinking it might be overkill - however considering the scenario I just thought of perhaps this is the best approach. The scenario being: what if the user changes the font size via the toolbar without scrolling the tableview? wouldn't this mean that "cellForRowAtIndexPath" might not be triggered? If so the question then is how to (a) initiate a layout view callback, and (b) within layoutViews to get the new version of the font? – Greg Mar 14 '11 at 01:45
  • It would mean `cellForRowAtIndexPath` would not be triggered. Even worse, if they scroll slowly they could have half the cells on the screen with the old font and half with the new. You tell a view to lay itself out by sending it `setNeedsLayout`. – Anomie Mar 14 '11 at 01:49
  • ok then, based on this and the advice from indragie it seems like either the [tableView reloadData] is in order, or at least at the minimum setNeedsLayout - thanks for the help – Greg Mar 14 '11 at 02:02
2

Accessing the UITableViewController object from within your cell isn't a good approach in terms of design. What you should be doing is creating an ivar in the table cell itself to store the UIFont object:

@interface CustomCell : UITableViewCell {
    UIFont *font;
}
@property (nonatomic, retain) UIFont *font;

And then in your tableView:cellForRowAtIndexPath method, set the font of the cell:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    ...
    [cell setFont:uiFont];
    ...
}
indragie
  • 18,002
  • 16
  • 95
  • 164
  • oh yes, I see what you mean indragie - will change my approach to this - thanks – Greg Mar 14 '11 at 01:34
  • oh actually what if the user changes the font size via the toolbar without scrolling the tableview? wouldn't this mean that "cellForRowAtIndexPath" might not be triggered? If so the question then is how to (a) initiate a layout view callback, and (b) within layoutViews to get the new version of the font? – Greg Mar 14 '11 at 01:44
  • When the user changes the font, just call [tableView reloadData]. That'll call cellForRowAtIndexPath and update the font. – indragie Mar 14 '11 at 01:55
  • oh OK - and I guess somewhere in that mix layoutSubviews would be called also then? – Greg Mar 14 '11 at 01:59
  • I'm not sure if calling `reloadData` would automatically call `layoutSubviews` as well. Try calling just `reloadData` first and if that doesn't do it, add a `layoutSubviews` call after it. – indragie Mar 14 '11 at 02:00