cocoaautolayoutnstableviewappkitnstableviewcell

NSView-based table view with auto layout grows, but does not shrink rows


I have a NSTableView in view-based mode (not cell-based) with usesAutomaticRowHeights=YES. The rows have dynamic height that might change at any time. This setup successfully grows table view rows (row content is never clipped), but table view rows don't shrink to the intrinsic row view height when rows get shorter. Calling noteHeightOfRowsWithIndexesChanged: on the table view after layout does not seem to fix the problem, my tableView:heightOfRow: is also not called again after noteHeightOfRowsWithIndexesChanged:.

Is there anything I have missed/isn't documented about using auto layout in NSView-based tableviews with variable row height? After all, growing rows always works without any additional code, they just do not shrink on their own.

NSTableView* tv = [[NSTableView alloc] init];

[tv setTranslatesAutoresizingMaskIntoConstraints:NO];
[tv setUsesAutomaticRowHeights:YES];     // Use auto layout for row height

NSTableColumn* column = [[NSTableColumn alloc] init];
[tv addTableColumn:column];

// Set table view data source and delegate, rows are then loaded...

Solution

  • After debugging the default table view layout for a long time, I finally found the issue. The table view row views come with some autoresizingmask settings that interfere with content, when using autolayout for the row content views. You need to set the row view's translatesAutoresizingMaskIntoConstraints to NO. This can be achieved for a view-based NSTableView using the delegate method tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row:

    - (void)tableView:(NSTableView *)tableView didAddRowView:(NSTableRowView *)rowView forRow:(NSInteger)row
    {   
        // Remember that rowView != row content view!
        [rowView setTranslatesAutoresizingMaskIntoConstraints:NO];   // Disable constraints interfering with row view content
    }
    

    Interestingly, this does not seem to be an issue if content does not shrink past the initial row height or maximum row height it has grown to, due to dynamic height increases.