5
votes

I'm trying to create a NSTableView inside a NSScrollView (the standard configuration, that is) in code, using auto layout. I can't figure out how to make this work.

Here's my loadView:

- (void)loadView
{
    NSView *view = [[NSView alloc] init];

    NSScrollView *tableScroll = [[NSScrollView alloc] init];
    NSTableView *fileTable = [[NSTableView alloc] init];
    [tableScroll setDocumentView:fileTable];
    [tableScroll setHasVerticalScroller:YES];
    [tableScroll setHasHorizontalScroller:NO];
    fileTable.delegate = self;
    fileTable.dataSource = self;
    [fileTable setHeaderView:nil];
    [fileTable setAllowsColumnReordering:NO];

    NSTableColumn *column = [[NSTableColumn alloc] initWithIdentifier:@"column1"];
    [fileTable addTableColumn:column];

    [tableScroll setTranslatesAutoresizingMaskIntoConstraints:NO];
    [fileTable setTranslatesAutoresizingMaskIntoConstraints:NO];

    [view addSubview:tableScroll];

    NSDictionary *topViews = NSDictionaryOfVariableBindings(tableScroll);
    [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[tableScroll]|" options:0 metrics:nil views:topViews]];
    [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[tableScroll]|" options:0 metrics:nil views:topViews]];

    self.fileTable = fileTable;

    self.view = view;
}

What happens is that my table view's frame will be always equal to the bounds of the NSClipView. The view is inside a window and gets resized with it, and when I do that it'll resize the scrollview, the clip view and the table, but I can never scroll anywhere.

Looking at constraints I get, the NSScrollView gets constraints that set the clip view to fill it, the clip view has no constraints at all and the table view has a bunch of constraints related to the NSTableRowViews inside it.

If I add a constraint like |[fileTable(>=500)] to the clip view I'll get 500 pixels of NSTableView, but obviously I don't want to do that.

1
If I set autoresizing mask for tableScroll, call setTranslatesAutoresizingMaskIntoConstraints:YES on tableScroll and fileTable and remove the two addConstraints calls, it works ok and I see NSAutoresizingMaskLayoutConstraint on the clip view that specify the exact size fileTable needs.Juri Pakaste

1 Answers

1
votes

Even though this was answered by the poster in the comments above, I thought I’d put the answer here (having run into the same issue). If you are adopting auto layout, you would typically uncheck “Translates Mask Into Constraints” in the xib. However, for classes like NSScrollView and NSTableView, you should generally let them manage their own internal views by setting their translatesAutoresizingMaskIntoConstraints property to YES. It is still ok to set constraints that are external to these views, i.e. to resize in relation to their superview.

If you set translatesAutoresizingMaskIntoConstraints to NO, then you will need to supply constraints for all of the internal views, which unless you specifically need custom behavior (almost never), you will not want to do. This was the specific problem above.

An obvious side effect of not setting this correctly is that a table (for example) will not properly scroll beyond what is visible in the view.