AppKit: Limit a NSTextView’s width and center it

Up: AppKit

Purpose:

The idea is to not actually give the NSTextView a maximum width, but instead give it a textContainerInset (i.e. padding) which increases to compensate for the width of the parent view, and also centers it width the left-hand-side and the right-hand-side always kept equal.

In your NSViewController subclass, define the maximum width, and the inset (padding):

class MyViewController: NSViewController {
  var maxWidth = 700.0
  var inset = 50.0

Make sure that the NSTextView’s textContainer does not automatically resize:

    textView.textContainer?.widthTracksTextView = false

In viewWillLayout(), set the container insets, dividing the excess width across the left and right insets:

  override func viewWillLayout() {
    super.viewWillLayout()
    
    let viewWidth = view.bounds.size.width

    if viewWidth > maxWidth {
      let leftover = (viewWidth - maxWidth)/2
      textView.textContainerInset =
        NSSize(width: inset + leftover, height: inset)
      textView.textContainer?.containerSize = NSSize(
        width: maxWidth - inset - inset,
        height: CGFloat.greatestFiniteMagnitude
      )
    } else {
      textView.textContainerInset =
        NSSize(width: inset, height: inset)
      textView.textContainer?.containerSize = NSSize(
        width: viewWidth - inset - inset,
        height: CGFloat.greatestFiniteMagnitude
      )
    }
  }
Note last edited May 2025.
Incoming links: AppKit.