NSScrollView is not like other views.
It does things just differently enough that it makes everyone crazy at first, and especially once you've gotten used to Auto Layout thinking.
It is also one of those views (along with NSTableView, NSOutlineView and NSCollectionView and more) where there are a lot of pieces to set up before you can start seeing things working. Auto Layout adds to this a bit, too.
NSScrollView contains at least 3 subviews by default:
- One NSClipView object. (Apple calls this the Content View. It is what
is visible.)
- Two NSScroller objects.
The NSClipView or Content View object contains an NSView of some sort.
(Apple calls this the Document View)
If you add a plain NSScrollView to your xib from the object library, that will appear to have a size in Interface Builder, but at run time it will have a zero size.
This will kick your butt every time.
You can see this by adding logging it.
NSLog(@" size of document view:%@", NSStringFromRect(_myScrollView.documentView.frame);
Even if you add a subview and call setNeedsDisplay:YES
all day long, you won't see a damn thing.
There are things you can do though.
First, you can set the size of the documentView with setFrameSize:NSMakeSize(somePointsWide, somePointsHigh)
You can also make it a custom NSView subclass that has an implementation of intrinsicContentSize
that figures this out based on whatever logic rules you want to put in there (including some default minimum).
You could also simply say that all subviews must be at least N points from the documentView or more on each edge with Auto Layout.
The VFL (visual format language) would look like this: @"H:|-nPoints-[aSubviewOfDocumentView]-nPoints-|"
and this @"V:|-nPoints-[aSubviewOfDocumentView]-nPoints-|"
(make sure your subviews have an intrinsic size or some subview of their own that gives them a minimum size... and implements - (BOOL)translatesAutoresizingMaskIntoConstraints { return NO; }
and turn off Auto Resizes Subviews for your documentView by the checkbox in IB, or by calling setAutoResizesSubviews:NO
or you'll be hating life.)
Now this leads to a weird thing.
With Auto Layout, it's generally good to stop thinking about frames and rects as much as possible, but with the NSScrollView documentView, you might want to consider not using Auto Layout for positioning subviews. In some cases it might be simpler not to, and just let the documentView grow to accommodate. If you use the above "nPoints" approach, and your subviews are draggable, you want to simply capture the NSPoint for the subview's frame origin (use it to determine your delta) and then the mouseDown point and when a drag finished, capture the mouse point and calculate the delta for your new frame origin point. Then call setFrameOrigin: with the new point.