1

As I understand, there seem to be three ways of laying out a custom table view cell:

  1. In Interface Builder.
  2. In layoutSubviews.
  3. In initWithStyle:reuseIdentifier:.

What's the difference between the second and third methods? Also, why not drawRect?

P.S. I'm following Chapter 9 of the book Pro iOS Table Views by Tim Duckett, where we're building custom UITableViewCells. The author shows how to lay out the cell in the same order as above, but I don't know whats the difference between the last two since they both do away with IB. I noticed, though, that the author simply sets the frames in layoutSubviews unlike in initWithStyle:reuseIdentifier: where properties concerning the look of a view are set (e.g., background image, background color, etc.).

Matthew Quiros
  • 13,385
  • 12
  • 87
  • 132
  • I usually do it like it is described in the book iOS recipes. This should be equivalent to the customization in `initWithStyle:reuseIdentifier:`. – dasdom Jul 31 '13 at 08:08

2 Answers2

4

You should create your cell subviews in

- initWithStyle: (UITableViewCellStyle) style reuseIdentifier: (NSString*) resueIdentifier

And layout them in layoutSubviews. -initWithStyle:reuseIdentifier method will be called once at initialization, but you cell may have incorrect frame at this moment.

Thats why you need to layout it in layoutSubviews method, it's called when cell needs to update layout, for example, when autorotation occurs. So if you will layout subviews in this method, you will have valid cell's frame and correct subviews layout.

Sahil Mahajan
  • 3,922
  • 2
  • 29
  • 43
Alexander Tkachenko
  • 3,221
  • 1
  • 33
  • 47
  • So I don't have to override `layoutSubviews` if I'm only supporting portrait orientation, correct? – Matthew Quiros Jul 31 '13 at 09:29
  • No, you should. Even if you have only portrait orientation, it's better to have all layout defined in that method. Cell frame may be incorrect in init method(for example, if you have custom height of the cell, and many another cases). And don't forget to call [super layoutSubviews]:) – Alexander Tkachenko Jul 31 '13 at 10:56
  • Thanks, I followed your tip about building everything in `initWithStyle:reuseIdentifier:` but did not override `layoutSubviews` just yet. I'm probably just being lazy but I don't think `layoutSubviews` will ever be called when the app doesn't do landscape and the table view cell is static: http://stackoverflow.com/a/5330162/855680. In the case cited above, it is `tableView:heightForRowAtIndexPath:` that has the final say on a custom table view cell's height anyway. What do you think? – Matthew Quiros Jul 31 '13 at 11:17
  • In the answer you've posted there is a point that layoutSubviews will be called when the view is added as subview. UITableViewCell is added as subview to UITableView. Besides, this answer concerns UIView, and in your case, UITableView adds its own behavior with additional places where layoutSubviews will get called. – Alexander Tkachenko Jul 31 '13 at 11:26
2
-[UIView layoutSubviews]

gives you much more control on the way a view is relayout (I suppose in your book example it is done in the table cell contentView). When you use a NIB file what you do is simply to recreate in memory the view hierarchy with some properties set, but the nib has not the dynamic capability to relayout a cell (or it is limited to the spring/struct or auto-layout capabilities). If you don't use the NIB you must create this hierarchy programmatically.

Especially in a table view cell subclass, you can add to it many properties that could change the way the cell is relayout, e.g. showing a thumbnail image or not, display a certain label or not, and in such cases you probably you need the layoutSubviews method to update the cell layout taking into account all the possible layouts due to different properties values.

viggio24
  • 12,316
  • 5
  • 41
  • 34