Well, I can’t figure out if IB supports your scenario in Xcode 9.2. In part, IB 
has some bugs in displaying the correct set of constraints error messages. In 
some cases, it displays errors for the wrong view; in some cases, it displays 
out-of-date messages until you rebuild the project, or close and re-open the 
project.

I did remember that Kyle Sluder had posted about this before, and I was able to 
track down this post here:

        
http://www.cocoabuilder.com/archive/cocoa/326783-guidelines-for-using-autolayout-with-nsscrollview.html#326786
 
<http://www.cocoabuilder.com/archive/cocoa/326783-guidelines-for-using-autolayout-with-nsscrollview.html#326786>

The relevant text is:

> The biggest issue with using auto layout in an NSScrollView's document view 
> is that NSScrollView itself is completely unaware of auto layout. Thus, it 
> relies on the behavior provided by setting 
> translatesAutoresizingMaskIntoConstraints=YES on its subviews so it can 
> continue to use -setFrame: to position them even if auto layout is turned on 
> for the window.
> 
> At this point it's worth noting another difference between NSScrollView and 
> UIScrollView: UIScrollView directly manipulates its own bounds.origin to 
> perform scrolling of its entire subview hierarchy. The contentSize property 
> dictates the size of the scrollable region.
> 
> NSScrollView, on the other hand, doesn't actually do any scrolling on its 
> own: it delegates that responsibility to an NSClipView. The scroll view 
> positions the clip view and scrollers (if they are visible) using -setFrame:. 
> Rather than exposing a contentSize property, NSClipView observes the frame of 
> _one specific subview_ called its documentView. This view's frame.size 
> becomes the equivalent of UIScrollView's contentSize.
> 
> In order to perform scrolling correctly, the documentView's frame.origin must 
> lie at (0,0) in the clip view's bounds coordinate system. NSClipView, like 
> NSScrollView, is unaware of auto layout, so it uses -setFrameOrigin: to put 
> the document view at (0,0). If auto layout gets turned on for the window, 
> this position gets turned into a pair of constraints with a priority of 1000 
> (required).
> 
> Two more constraints will be synthesized to define the width and height of 
> the document view. These constraints are the problem. In either direction, 
> one of two kinds of constraints will be generated, depending on the 
> documentView's autoresizing mask for that direction:
> 
> 1. If the view is stretchable in that direction, a constraint will be 
> installed relating the opposing edge of the documentView to the edge of the 
> superview.
> 
> 2. If the view is not stretchable in that direction, a constraint will be 
> installed dictating the absolute value of the documentView's frame.size in 
> that dimension.
> 
> Like all autoresizing-mask constraints, these constraints are required 
> (priority 1000). Because the entire constraint system is solved at once, it 
> should be intuitive that any constraints that attempt to influence the size 
> of the documentView will conflict with either the constraints installed by 
> the clip view on the documentView and/or with the constraints installed by 
> the scroll view on the clip view.
> 
> So we have a dilemma. We need to somehow break the bidirectionality of the 
> relationship between the clip view and the documentView. There is no 
> straightforward way to express this using the constraints API, but it is 
> indeed possible without resorting to mucking with private internal details.
> 
> In other words, we want to somehow run layout of arbitrary constraints on our 
> documentView's subtree and retrieve the resultant frame of the documentView 
> without involving the documentView itself in our constraint system. Once we 
> have the right values, we can use -setFrameSize: on the documentView; the 
> clip view will notice and it will update its scrollable area.
> 
> The way we accomplish this is to install another view in our subtree and 
> define all our constraints relative to _that_ view. I'm going to call this 
> the adaptor view. The documentView installs constraints to keep the adaptor 
> view's top and leading margins equal to zero, but critically it does NOT 
> install any constraints on the trailing or bottom edges. This leaves the 
> adaptorView's width and height free to be defined by its content's layout.
> 
> The documentView signs up for frame change notifications from the adaptor 
> view. Whenever it changes its frame, the documentView calls [self 
> setFrameSize:] with the same size.  Then the clip view hears about this, and 
> the scroll view reflects the correct document size. For this to work, the 
> documentView's autoresizing mask should be set to width and height 
> NON-stretchable, that way when the clip view resizes (perhaps during window 
> dragging) it doesn't resize your documentView.
> 
> If you're laying out the contents of your scroll view in IB, the most 
> convenient approach is to make the adaptor view the only subview of your 
> documentView, and to add all your widgets as subviews of the adaptor view. 
> The bonus here is that if your constraints are insufficient to fully specify 
> the frame of the adaptor view, IB will doggedly insist on adding margin or 
> fixed-size constraints until you fix your layout. Yes, we have turned one of 
> IB's most annoying habits into a feature!
> 
> If you're generating all your constraints in code, however, it might be just 
> as convenient to make your adaptor view a _sibling_ of all your widgets and 
> to call -setHidden:YES on it, thus removing a level of hierarchy between the 
> documentView and your widgets.


I think this is basically all still true, and I think it describes a solution 
to your problem.


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to