1
votes

According to Apple's documentation on [NSTableViewDelegate tableView:sizeToFitWidthOfColumn:]:

By default, NSTableView iterates every row in the table, accesses a cell via preparedCellAtColumn:row:, and requests the cellSize to find the appropriate largest width to use.

For accurate results and performance, it’s recommended that this method is implemented when using large tables. By default, large tables use a monte carlo simulation instead of iterating every row.

This default behavior is exactly what I want, so I choose not to implement this method in my NSTableViewDelegate. However, when I double click a column’s resize divider, nothing happens. My table view is view-based.

1

1 Answers

1
votes

As of OS X 10.10.2, columns in view-based table views still do not auto-size when double-clicking the column separator.

I implemented the delegate to sample rows of the visible rect as well as 50 rows below and above.

- (CGFloat)tableView:(NSTableView *)tableView sizeToFitWidthOfColumn:(NSInteger)column
{
    // Note: Called on double-click of table columns separator
    // Note: As of 10.10.2, [NSTableView _sizeToFitWidthOfColumn] does nothing for view-based table views
    NSRect          visibleRect     = tableView.visibleRect;
    NSRange         rowRange        = [tableView rowsInRect:visibleRect];
    NSUInteger      numberOfRows    = tableView.numberOfRows;
    NSInteger       minRow          = rowRange.location;
    NSInteger       maxRow          = rowRange.location + rowRange.length;

    minRow  = MAX(0, minRow - 50);
    maxRow  = MIN(numberOfRows, maxRow + 50);

    NSTableColumn   *tableColumn    = [[tableView tableColumns] objectAtIndex:column];
    CGFloat         minWidth        = tableColumn.minWidth;
    CGFloat         maxWidth        = tableColumn.maxWidth;
    CGFloat         width           = minWidth;

    /*
     NSCell         *headerCell     = tableColumn.headerCell;

     if ([headerCell isKindOfClass:[NSCell class]]) {
        NSRect  bounds          = NSMakeRect(0.0f, 0.0f, maxWidth, headerCell.cellSize.height);
        CGFloat fittingWidth    = [headerCell cellSizeForBounds:bounds].width;

        if (fittingWidth > width) {
            width = fittingWidth;
        }
     }
     */
    for (NSInteger row = minRow; row < maxRow; row++) {
        NSTableCellView *tableCellView  = [tableView viewAtColumn:column row:row makeIfNecessary:YES];
        CGFloat         fittingWidth    = [tableCellView fittingSize].width;

        if (fittingWidth > width) {
            width = fittingWidth;

            if (width >= maxWidth) {
                break;
            }
        }
    }

    return MIN(maxWidth, width);
}