Search code examples
nsviewappkitnsscrollview

Why doesn't overriding `intrinsicContentSize` in `NSView` work for `NSScrollView`?


I have placed an instance of custom class BigView that is a subclass of NSView inside a NSScrollView in IB. The content size of my BigView will be computed at runtime. What is the best practices for setting the content size?

Overriding intrinsicContentSize, as suggested in the The Big Nerd Ranch guide, does not seem to work -- the frame remains at its original size:

class BigView: NSView {
   ...
   override var intrinsicContentSize: NSSize { // doesn't work?!
      return NSSize(width: 10000, height: 10000)
   }
   ...
 }

Setting the frame programmatically (or in IB) does work:

class BigView: NSView {
   ...
    override func awakeFromNib() {
       ...
       self.frame = NSRect(x: 0, y: 0, width: 10000, height: 10000)
    }
    ...
}I 

or from the controller:

class ViewController: NSViewController {
   @IBOutlet weak var bigView: BigView!
   ...
   override func viewDidLoad() {
       super.viewDidLoad()
       bigView.frame = NSRect(x: 0, y: 0, width: 1000, height: 1000)
   }
   ...
}

This can also be done throughout the scrollview's documentView property:

class ViewController: NSViewController {
   @IBOutlet weak var scrollView: NSScrollView!
   ...
   override func viewDidLoad() {
       super.viewDidLoad()
       scrollView.documentView?.frame = NSRect(x: 0, y: 0, 
                                               width: 1000, height: 1000)
   }
   ...
}

I suppose one could also use AutoLayout constraints as well.

What doesn't overriding intrinsicContentSize work?


Solution

  • The problem is that when translatesAutoresizingMaskIntoConstraints is enabled in newer versions of AppKit default constraints are set without considering the intrinsic size.

    To fix this you need to add the constraints manually. First pin the position of your BigView to the top left of the superview (Should be the NSClipView). Then go to the Size Inspector, and in the Content Compression Resistance Priority section set Intrinsic Size to Placeholder. That gives your view the constraints it needs and everything should work at runtime.