Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
656 views
in Technique[技术] by (71.8m points)

objective c - Automatically adjust height of a NSTableView

I have asked this question once before, but I'm just not very satisfied with the solution.

Automatically adjust size of NSTableView

I want to display a NSTableView in a NSPopover, or in a NSWindow.
Now, the window's size should adjust with the table view.

Just like Xcode does it:


enter image description here enter image description here


This is fairly simple with Auto Layout, you can just pin the inner view to the super view.

My problem is, that I can't figure out the optimal height of the table view. The following code enumerates all available rows, but it doesn't return the correct value, because the table view has other elements like separators, and the table head.

- (CGFloat)heightOfAllRows:(NSTableView *)tableView {
    CGFloat __block height;
    [tableView enumerateAvailableRowViewsUsingBlock:^(NSTableRowView *rowView, NSInteger row) {
        // tried it with this one
        height += rowView.frame.size.height;

        // and this one
        // height += [self tableView:nil heightOfRow:row];
    }];

    return height;
}

1. Question

How can I fix this? How can I correctly calculate the required height of the table view.

2. Question

Where should I run this code?
I don't want to implement this in a controller, because it's definitely something that the table view should handle itself.
And I didn't even find any helpful delegate methods.

So I figured best would be if you could subclass NSTableView.
So my question 2, where to implement it?


Motivation

Definitely worth a bounty

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This answer is for Swift 4, targeting macOS 10.10 and later:

1. Answer

You can use the table view's fittingSize to calculate the size of your popover.

tableView.needsLayout = true
tableView.layoutSubtreeIfNeeded()

let height = tableView.fittingSize.height

2. Answer

I understand your desire to move that code out of the view controller but since the table view itself knows nothing about the number of items (only through delegation) or model changes, I would put that in the view controller. Since macOS 10.10, you can use preferredContentSize on your NSViewController inside a popover to set the size.

func updatePreferredContentSize() {
    tableView.needsLayout = true
    tableView.layoutSubtreeIfNeeded()

    let height = tableView.fittingSize.height
    let width: CGFloat = 320

    preferredContentSize = CGSize(width: width, height: height)
}

In my example, I'm using a fixed width but you could also use the calculated one (haven't tested it yet).

You would want to call the update method whenever your data source changes and/or when you're about to display the popover.

I hope this solves your problem!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...