When in the view lifecycle does UITableViewCell create its outlets/labels/subviews?
ios, objective-c, uitableview, uiview
Solution
Generally speaking, objects should create their properties in their designated initializer, unless there is an overriding design principle (or a performance/resource issue) which mandates that they create them later.
The designated initializer for `UIView` (and `NSView` on OS X) is `-initWithFrame:`. The designated initializer for `UITableView` is `initWithFrame:style:`. Since a view will usually need to have it's visible subviews available immediately upon being added to its superview, it is fine to create and set them in the designated initializer.
`-layoutSubviews` is intended for updating the layout, which is to say the center, bounds (or frame) and (optionally) transform. Now, because of the ordering of messages. You don't want to create your subviews in `-layoutSubviews` because that method gets invoked repeatedly during the lifetime of your view, as its parent view's bounds changed and as it gets removed or re-added to its parent view, or as its subviews change.
In the case of UITableView, `-layoutSubviews` is called every time the table is reloaded.
A typical exception to this rule is the creation of `UITableViewCell`s used as rows of the table, which must be created dynamically.
The `-heightForRowAtIndexPath` method provides a table view with the amount of space it needs to leave for that row's cell, but doesn't actually cause the cell to be resized. YOu have to set the cell's bounds yourself when creating the cell (or the cell can set its own bounds in `-initWithStyle:reuseIdentifier:`, if it's designed to be a fixed value). IF your cell's size does not match the table's expectations, you will get gaps or overlaps.
For autoresizing masks to work properly, you must configure the view's initial frame yourself (either in code or in a nib). Autoresizing a view affects how it responds to changes in its parent view's bounds, but does not help in determining the view's initial frame.
Specifically, you must set the initial frames for subviews of your cells (and also ensure sibling subview ordering, etc). This is easier to do in nibs than in code.
Problem
I am trying to create a `UIView` as a subview of a subclassed `UITableViewCell`. Essentially I want a view which is the same size as the cell, and sits between the cell's `contentView` and `backgroundView`. I imagine that somewhere under the hood (possibly in `layoutSubviews`), there is a line in `UITableViewCell.m` something like: ``` if (self.contentView != nil) { [self addSubview:self.contentView]; } ``` If I want to mimic the way Apple does it, where should I put this code in my own custom `UITableViewCell` subclass? Also, in my first attempted implementation, the subview is displayed but it has the default cell height of 44px rather than the height I specified in `tableView:heightForRowAtIndexPath:`. There are also other small bugs that show up, which is why I'd like to try and replicate Apple's implementation rather than try my own semi-functional one. EDIT: Here's my code so far: In `CustomTableViewCell.h` ``` interface CustomTableViewCell : UITableViewCell @property (nonatomic, strong) UIView *newSubview; @end ``` In `CustomTableViewCell.m` ``` - (void)layoutSubviews { [super layoutSubviews]; if (self.newSubview != nil) { self.newSubview.autoresizingMask = UIViewAutoresizingFlexibleHeight; [self insertSubview:self.newSubview aboveSubview:self.backgroundView]; } } ``` In `tableViewController.m` ``` static NSString *CellIdentifier = @"Cell"; myCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } UIView *view = [[UIView alloc] initWithFrame:cell.frame]; view.backgroundColor = [UIColor orangeColor]; cell.newSubview = view; ```