Layout still needs update after calling NSTableRowView layout - macos

I have two NSTableView's in my app and the user can drag and drop items from table A to table B. When dragging an item to table B Xcode gives me the following layout warning message:
Layout still needs update after calling -[NSTableRowView layout].
NSTableRowView or one of its superclasses may have overridden -layout
without calling super. Or, something may have dirtied layout in the
middle of updating it. Both are programming errors in Cocoa
Autolayout. The former is pretty likely to arise if some pre-Cocoa
Autolayout class had a method called layout, but it should be fixed.
This ever only happens when items are dragged to table B. I have otherwise no auto-layout warnings in IB and everything in the layout looks like being set up correctly. Does somebody know what the above message is trying to tell me? The tables are using standard Cocoa classes (not sub-classed).

I fixed it (or rather worked around it) by having the drop operation type not being allowed except for NSTableViewDropOperation.Above. Before a user could drop them onto other rows, not just between rows. But I want them to be only be allowed to be dropped between rows so that's fine with me. Here's the code that fixed it:
func tableView(aTableView:NSTableView, validateDrop info:NSDraggingInfo, proposedRow row:Int, proposedDropOperation operation:NSTableViewDropOperation) -> NSDragOperation
{
if (operation == .Above) { return .Move; }
return .None;
}

In my case the warning was slightly different.
Layout still needs update after calling -[NSView layout]. NSView or
one of its superclasses may have overridden -layout without calling
super. Or, something may have dirtied layout in the middle of updating
it. Both are programming errors in Cocoa Autolayout. The former is
pretty likely to arise if some pre-Cocoa Autolayout class had a method
called layout, but it should be fixed.
Different class NSView.
Anyway in my case, I could fix this by setting translatesAutoresizingMaskIntoConstraints == false of a NSScrollView.
For the record, autoresizingMask and autoresizesSubviews don't need to be touched at all.
The warning simply means that I have to set the property manually, otherwise it will produce wrong constraints. But figuring out the problematic object was very hard. I had to iterate all view nodes to check the property state.

Related

Xcode Interface Builder 9.1 Collection View Cells have too small "expected height"

Recently, I encountered a problem with the Interface Builder which I failed to solve. I'm using a UICollectionViewController and whenever I add a Cell it immediately shows a orange rectangle (indicating a auto-layout update). Updating the frame/cell doesn't change anything. The warning associated with the orange marking reads "Expected: height=Y, Actual: height=X" where Y is always exactly X-100. That is: When I set a custom cell height of 193, it says "Expected: height=93". This happens no matter which size I enter.
The problem with this is that I have many difficulties with the subviews and their constraints. For instance, if I add a subview with the constraint to keep the same height as the cell, it will be shown as 93 (the expected height), even though my cell should be 193. Layouting becomes impossible.
I tried adding a new cell, same issue. I tried removing every subview and re-adding them, nothing.
Any ideas are highly welcome.
Thank you very much!
Solution found ! (Xcode 9.2)
The bug seems to only happen when you try to embed the UICollectionViewController in a Container View in the storyboard. The workaround is to remove the segue while you set your constraints, and re-add the segue once your constraints are well set.
I also think that setting UICollectionViewController size as Freeform could be responsible of the bug. If so, try to set constraints before changing the size.
Hope this helps !
I'm not sure if this solved it, but the warning and issue disappeared once I did the following:
Select the CollectionViewController in Interface Builder and set the size to freeform and make the height larger, large enough to show all your template cells. (Plus: maybe refresh the views). That solved the issue for me.
In my case, I have added two collection view cell, withing collection view Controller.Only setting the view controller to free form wont help us. Need to update the size, to get rid of the warning.
updating collection view cell frames, wont help us. Warning will be continuously changing its length.
I tried to work without considering the warning, as I have set my collection view cell size programmatically and it does working as expected.
I think it's just a strange bug
I delete the collectionViewController in SB, then create a new one, the problem disappear
This is a common bug with Interface Builder. I don't know the exact cause, but I believe it's something to do with placing collection views inside arrangement views that do not have an exact size. I've seen it when putting them in scroll views, stack views and container views.
There is a simple fix, although I believe this to be a bug in IB that ought to be corrected by Apple rather than hacking around it. The solution (for me at least - your mileage may vary!) is to place the collection view inside an ordinary UIView and pin its edges to it, then place that parent view in the position that you wanted your collection view with all the constraints it required.
I usually found that there were actually no auto layout issues at run-time, which is why I believe this to be purely an Interface Builder bug.

macOS Printing in Swift

Please note this is not an iOS question.
I have an NSView-based app (i.e. not document-based), and I’d like to bolt on a printing subsystem. I can get NSViews in my main controller to print ok. However, I want to have a special view constructed just for printing. The view should not show in the app’s window. The view contains two NSTextFields, two NSTextViews, and 5 labels.
I cannot seem to figure out a way to do this. I have tried various forms of these examples:
Add an NSView to my main view window? Seems logical, but it’s awkward in a storyboard, (I can’t position the view in the storyboard).
Programmatically create a custom NSView with a xib?
For this, I’ve tried:
#IBOutlet weak var printView: NSView!
….
let printOperation = NSPrintOperation(view: printView!)
This results in the comprehensive "fatal error: unexpectedly found nil while unwrapping an Optional value” message.
The outlets are configured correctly (I think)
A seperate ViewController? If so, how can I avoid having two print buttons — one to call the print controller, and the second, to print the PrintController’s view.
I’ve tried reading the Apple docs, but they are not the way I learn best. There are also no Print documents in Swift that I've found. I’ve waded through many SE questions, but have come up blank. Could you point me towards a solution please.
I think the specific problem here is that you're never causing the view to be loaded.
You can double check whether this is the case by overriding the viewDidLoad method on the controller. If it's never called, your view is never loaded from the nib.
Normally the UI machinery takes care of all that when you display a view controller, which is why it can be so confusing when it doesn't happen.
You should be able to trigger the view load by accessing the view property on the controller. e.g.
_ = self.view // Touch the view to force it to load
https://developer.apple.com/documentation/appkit/nsviewcontroller/1434401-view has some additional information.
You can also call loadView() directly although that's usually frowned upon.

NSTableView inside NSOutlineView and NSView-Encapsulated-Layout-Height

I'm building a OS X application using Swift and Xcode 6.4 on OS X 10.10.5.
On a specific view of my application I would like to have a view like this one Xcode has on the Data Model Editor.
I tried to replicate this view using an OutlineView where each "row" would have a title and a TableView plus two buttons (for the plus and minus buttons). For tests purposes I've separated the title for the TableView+Buttons, something like this (this was one of many different attempts).
Everything is working as expected except the View that has the TableView+Buttons, that is never higher than 17 pixels. If I define everything in one view, I have the same problem. I've tried defining the needed constraints but in that case there is a problem with a constraint that seems automatic called NSView-Encapsulated-Layout-Height, that forces the height to 17 pixels:
NSLayoutConstraint:0x61800008ea10 'NSView-Encapsulated-Layout-Height'
> V:[NotesTable(17)] (Names: NotesTable:0x60000012e2e0 )
I'm not defining any constraint to 17 pixels, I've tried testing with some parameters that usually insert automatic constraints (autoresizesSubviews/translatesAutoresizingMaskIntoConstraints/autoresizingMask) but I was only able to translate that 'special' constraint to another format and the grow doesn't get bigger.
Tried to search the web but I only get cases where that Encapsulated constraint makes sense and is useful.
Do you know where or how can I disable that constraint or change its value to the height I need?
Table and outline views on OS X do not support automatically determining the row height from the dynamic height of the cell views. They either have an explicit static row height, a static row height determined by the design-time height of the cell views, or a dynamic row height determined by the delegate and its implementation of -tableView:heightOfRow: or -outlineView:heightOfRowByItem:.
For your case, you're going to have to implement the delegate method. Furthermore, the delegate method can't query the actual cell view because it may not exist and the outline view would need the row height before creating it. So, the delegate has to compute it some other way.
One way is to keep a standalone view hierarchy of a prototypical cell view. When the delegate is asked for the row height, it configures that view hierarchy as it would be for the actual cell view for that row/item, forces it to lay itself out, and then queries its height. Configuring the view hierarchy may be as simple as setting the objectValue of the top-level view (if it's an NSTableCellView, a control, or otherwise implements the setter). But if your delegate does other configuration, such as in its -outlineView:viewForTableColumn:item: method, then you'll need to replicate that for this prototype view hierarchy.
Also, when any factor that would affect a row's height changes, you have to call the outline view's -noteHeightOfRowsWithIndexesChanged: method to let it know that, so it will re-query your ...heightOfRow... method.
Finally, bare table views are not especially amenable to being constrained to sibling views or their superview. They really want to live in scroll views and continue using springs-and-struts to position and size themselves. See my answer to another question for a discussion of this. It is possible that this has been improved in recent versions of the OS. Anyway, you're going to have to observe the table view's frame-change notifications (and ask it to post such notifications) in order to know when it grows. And your ability to set constraints to relate it to any other views in the cell view hierarchy will be severely limited, because it will need translatesAutoresizingMaskIntoConstraints turned on.

Leaving inputAccessoryView visible after keyboard is dismissed iOS8?

I want to make behavior like messaging app. I have been browsing Stack Overflow for solutions for this, and indeed there are plenty:
Leaving inputAccessoryView visible after keyboard is dismissed
This was the one that I found. But it seems things are a little different in iOS8. If I do the same thing in new iOS8 sdk, i get error:
'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<UICompatibilityInputViewController: 0x7fdcb3441b10> should have parent view controller:<ViewController: 0x7fdcb3b1e9f0> but requested parent is:<UIInputWindowController: 0x7fdcb684c000>'
In order to test this more I made a sample project, just one controller with view on the bottom:
Outlet is connected to bottom view, that only has UITextField on it. Am I missing something and how do i get the desired behvior?
iOS8 has a retain cycle with the inputAccessoryView. Here's a good post that seems to have a good workaround:
http://derpturkey.com/uitextfield-docked-like-ios-messenger/
You are adding the someView to multiple superViews, which leads to inconsistent hierarchies (which it is telling you).
When the keyboard gets activated, it calls the inputAccessoryView() method to see if it needs to stick anything on top of the keyboard, and adds that to its own superView. But you already added it to the view through your storyboard.
Now there are 2 ways you can solve this:
Make a .xib with your view and return that one in your inputAccessoryView(), not adding it to any superview yourself (the keyboard will.
Or make it completely in code using NSLayoutConstraint.
You can add the following code to your ViewController which will persist the view even when the keyboard is hidden.
override func canBecomeFirstResponder() -> Bool {
return true
}
Look at this GitHub repo for an example.

Problem using autolayout feature of Mac os Lion

I am using autolayout feature for my mac app.I have enabled autolayout for my mainWindow & also for its child views.But on expanding window , only my window expands in size but not the child views.And on app launch I get following message in the console
"Layout still needs update after calling -[WebHTMLView layout]. WebHTMLView or one of its superclasses may have overridden -layout without calling super. Or, something may have dirtied layout in the middle of updating it. Both are programming errors in Cocoa Autolayout. The former is pretty likely to arise if some pre-Cocoa Autolayout class had a method called layout, but it should be fixed."
Please help!
The log is probably not related to your issue.
For your issue, select a view that you expect to stay pinned to the side of your window but isn't. You should see the constraints involving that view drawn as blue. It'll stay pinned if and only if you see a constraint there that pins it. You can explicitly add constraints with the Editor > Align and Editor > Pin menus.
The log is because web view implements that method and needs to rev, but it's mostly[1] harmless.
[1] Possibly html layout in the web view ends up triggering more often than necessary.
Did you check if
WebHTMLView or one of its superclasses may have overridden -layout
without calling super.
like the error text explains? WebHTMLView is your class?
As they say:
The former is pretty likely to arise if some pre-Cocoa Autolayout
class had a method called layout, but it should be fixed.

Resources