I'm seeing kind of a weird bug with NSTableView/NSOutlineView and auto layout.
When I add an NSOutlineView to my nib and run the app, it will get bigger as expected from the given constraints, but it will never get smaller than the size it was in the nib. It's like it has an invisible "greater than or equal" constraint on it.
I have tested a few variations, and it seems that both NSTableView and NSOutlineView (inside the automatic scroll view) behave this way, but a plain scroll view with no content does not.
Please see the NSTableColumn documentation which states
minWidth
Returns the table column’s minimum width.
(CGFloat) minWidth
Return Value
The minimum width of the table column, in points. The default value is 10.0.
Related
Since macOS 10.13 we can use NSTableView with automatic row heights, thanks to the new property usesAutomaticRowHeights and of course auto layout. This works quite nicely.
But when the user resizes a column, the calculated heights are no longer correct, and gaps appear in the tableview cells.
Is there a proven way to update the row heights after column resize in this scenario?
I already tried methods like updateConstraintsForSubtreeIfNeeded(), updateConstraints(), setNeedsDisplay(), reloadData() and so on, but nothing works.
If you use NSTextField's in your design, make sure the Desired Width setting of each NSTextField with dynamic height, is set to Automatic. This setting is located in the Size Inspector.
Changing this resulted in automatic recalculation of the tableview row heights.
Something that worked for me was to include the tableViewColumnDidResize notification method in the NSTableviewDelegate. There you can call the noteHeightOfRows method of the table view. Here is an implementation:
//Recalculate when the screen moves
func tableViewColumnDidResize(_ notification: Notification) {
let allIndex = IndexSet(integersIn:0..<self.YOURTABLE.numberOfRows)
YOURTABLE.noteHeightOfRows(withIndexesChanged: allIndex)
}
Here are the links to the documentation: tableViewColumnDidResize and noteHeightOfRows
(I don't know english well). I have a question: can you show an example of my problem. I want to make expanding list. i.e. i have a controller view and when I click on one of strings there appears a list with data of this strong under it, and other string shift below.
You can achieve this with an additional(!) constraint for the height, by which you can set the view's height to zero:
Define this constraint in the storyboard (or code).
Create an outlet property to the constraint. This must be a strong property because of deactivating a constraint will remove it from the corresponding views.
Give this constraint the highest priority. Other constraints which influence the hight should have smaller priorities.
You can now hide and show the view by activating and deactivating the constraint.
Animation of the change can be done with UIKit animations:
UIView *theView = self.view; // Must be a parent of the animated view
self.heightConstraint.active = isHidden;
[UIView animateWithDuration:0.25 animations:^{
[theView layoutIfNeeded];
}
I'm currently implementing drag and drop rearranging in a table view in my OS X app. While normal scrolling works fine, autoscroll while dragging it totally broken.
If I grab a cell and start dragging, autoscroll just tells the table to scroll to the top. If I manually scroll using the trackpad during dragging the table continually pops to the top. If I drag one of the top cells, the table will not autoscroll down when dragging near the bottom.
I subclassed NSScrollView and overrode the scrollClipView method. I see that it's being called by some internal autoscroll method with the coordinates of (0, 0).
Since I can't see what that internal method is doing, and Goggle and SO are turning up nothing, I'm a bit stuck.
Has anyone run into this issue before? From past experiences, I have the feeling it's something AutoLayout related, but I have no idea what. Or maybe it's something completely unrelated.
Any ideas on how to further troubleshoot?
I ran into the same issue. In my case, the problem was that I set the height of the NSTableCellView to 10,000 in Interface Builder so that the horizontal separators wouldn’t be displayed for empty rows below the actual rows.
However, the actual height of my NSTableCellViews loaded at run time was 43px.
So as soon as I started dragging a cell to re-order it, the NSScrollView was trying to scroll 10,000 pixels at a time instead of 43 at a time.
This seems like a bug, because my NSOutlineView subclass does implement the following method to dynamically set the height of each row.
func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat
Apparently that method is ignored by the autoscroll mechanism during drag and drop operations, and only the value set in Interface Builder is used.
So I just changed the height of the dummy NSTableCellView to 43px in Interface Builder, and I’ll just live with the horizontal separators being displayed for empty rows.
I'm having trouble getting a UIScrollView to respect the constraints I put in interface builder.
All I need to be able to do is set the content size of the scroll view from within IB.
The UIScrollView contains a single UIView.
Constraints on the UIScrollView:
Constraints on the UIView:
I've read through the documentation, and so have set things up as follows:
the UIScrollView has constraints pinning it to its superview, thus defining its size from outside
the UIView (content) has a fixed size (through width and height constraints)
the UIView is pinned to the UIScrollView, thus defining the content size
However, IB won't let me enter these constraints. If I change the 'Bottom Space' constraint between the view and the scroll view, shown in the image as -2196, to 0 (thus pinning the lower edge of the scroll view), then the 'Top Space' constraint resets to a non-zero value. The same happens in reverse. (I haven't yet tried in Xcode 5, which has a far saner approach to invalid constraints in that it doesn't just throw yours away when it feels like it.)
What am I missing?
Every time I've tried to do something even mildly sophisticated with constraints in Xcode 4's Interface Builder, I've eventually given up and either written the constraints in code or switched back to springs'n'struts and layoutSubviews (usually after crashing Xcode a few times).
That said, there is another approach to laying out a scroll view with content in IB. Just make the scroll view as big as its content size, and rely on the view controller (or some containing view controller) to resize the scroll view (or its superview) and let the constraints shrink down the scroll view's frame at runtime. The window's root view controller will always set its view's frame to the screen size, regardless of its size in the nib or storyboard, and that resizing flows down the view hierarchy.
I described this approach in more detail in this answer.
If your scroll view's content size is really supposed to be 2196 points tall, this probably won't work so well. I don't have anything better to suggest in that case.
In my storyboard file I am designing multiple prototype cells in a UITableView. Each cell has its own unique Cell Identifier.
Depending on the section and the row I dequeue one of the prototype cells in method - tableView:cellForRowAtIndexPath:
For most of the prototype cells I have not changed the Row Height. On my storyboard, their height seems to be determined by the property 'Row Height' under 'Size Inspector' of UITableView.
For one prototype cell I have changed the height through the property 'Row Height' under 'Size Inspector' of the specific UITableViewCell. The checkbox 'Custom' is also checked.
On my storyboard this seem to work well. But during runtime when my cells are being dequeued and added to the TableView, all cells get the default row height.
Now, I am aware of the method tableView:heightForRowAtIndexPath: which is being mentioned in other posts but it seems a little odd to use as I am setting a custom row height in my storyboard already.
Does somebody know why this property is not working? Is this property maybe mend to be used in different situations?
Thanks
If you want to use Interface Builder in Xcode 5 to change the height of the rows in a table view without code you can do it in two places:
Select the table view, show the Size inspector and type it in
Row Height, in the Table View Size section.
Select the prototype cell, show the Size inspector, check Custom in the Table View Size section and type the row height in the associate text field.
Could it be that you're using the second method? Try to use the first method to set the default height of all the rows in the table view and the second to tell Interface Builder about the exceptions.
heightForRowAtIndexPath is called (for each row of the table) before the cells are displayed, i.e. before cellForRowAtIndexPath is called. That is necessary to compute the layout of the underlying scrollview, the scroll indicators etc.