indentationLevelForRowAtIndexPath not indenting custom cell

I have overridden the tableView:indentationLevelForRowAtIndexPath method in my UITableViewController derived class as follows:

- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
    int indentationLevel = [[item objectForKey:@"indent"] intValue];
    DLog (@"Indentation Level for Row %d : %d", indexPath.row, indentationLevel);
    return indentationLevel;
}

I initially thought that this was not being called but that was operator error (err, mine) and I hadn't defined the symbol DEBUG=1.

However, it is being called (duh me!) and this is the log output:

 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 0 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 1 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 2 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 3 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 4 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 5 : 1
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 6 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 7 : 2
 -[RootViewController tableView:indentationLevelForRowAtIndexPath:] [Line 129] Indentation Level for Row 8 : 1

But, this is not affecting the layout of the cells. No indentation.

This is my itemCellForRowAtIndexPath implementation, if that makes any difference:

-(UITableViewCell*)tableView:(UITableView *)tableView itemCellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString* cellIdentifier = @"projectItemCell";
    ProjectItemTableViewCell* cell = (ProjectItemTableViewCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    if (cell == nil) {
        NSArray* nib = [[NSBundle mainBundle] loadNibNamed:@"ProjectItemTableViewCell" owner:self options:nil];
        for (id oneObject in nib) {
            if ([oneObject isKindOfClass:[ProjectItemTableViewCell class]]) {
                cell = (ProjectItemTableViewCell*)oneObject;
            }
        }
    }

    NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
    cell.projectDescLabel.text = [item objectForKey:@"name"];
    cell.itemCountlabel.text = [NSString stringWithFormat:@"%d", [[item objectForKey:@"cache_count"] intValue]];
    cell.itemCountlabel.backgroundColor = [UIColor colorForHex:[item objectForKey:@"color"]];
    cell.indentationWidth = 20;
    return cell;
}

How do I indent a custom UITableViewCell which I have defined in Interface Builder?

If I change the itemCellForRowAtIndexPath to use a default UITableViewCell with the code below, then it indents fine.

static NSString* cellIdentifier = @"projectItemCell";
UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
}

NSDictionary* item = [self.projects objectAtIndex:indexPath.row];
cell.textLabel.text = [item objectForKey:@"name"];
cell.indentationWidth = 40;

return cell;

Yeah, it seems like custom table cells don't do this automatically? You need to override the layoutSubviews method in the table cell class. See this question for how to do this.

This code worked perfectly for me (although be careful if you are setting a custom height w/ the delegate as well, they seem to interfere with each other):

- (void)layoutSubviews
{
    [super layoutSubviews];
    float indentPoints = self.indentationLevel * self.indentationWidth;

    self.contentView.frame = CGRectMake(
        indentPoints,
        self.contentView.frame.origin.y,
        self.contentView.frame.size.width - indentPoints, 
        self.contentView.frame.size.height
    );
}

Edit for iOS8 and later

The above does work for me on iOS, but it causes subtle bugs when trying to autosize the height of the cell as well. There is n easier solution: If you have autolayout turned for the cell just set the left margin of the contentView:

override func layoutSubviews() {
    super.layoutSubviews()
    self.contentView.layoutMargins.left = CGFloat(self.indentationLevel) * self.indentationWidth
    self.contentView.layoutIfNeeded()
}

If you use a custom cell with constraints, the most convenient way is to set up a constraint that would shift all content from the left edge, and then update it according to the indentation level in your cell subclass.

Assuming indentationWidth is already set for the cell:

override var indentationLevel: Int {
    didSet {
        self.leftConstraint.constant = CGFloat(self.indentationLevel) * self.indentationWidth
    }
}

The indentation level is a property of the UITableViewCell itself. Try setting it on the cell when you create it, and return this value in tableView:indentationLevelForRowAtIndexPath:


Have you added the subviews of your ProjectItemTableViewCell to the cell's contentView? Also, you need to set the subviews' autoresizing masks so that they are repositioned when the contentView size changes.