If you’re adding a subview programmatically, you may run into having to constantly set all the resizing behaviors and/or anchors manually when all you really want to do is fill the whole available area based on two options: “stretch me to fit this box” or “stretch this box so I can fit”.
This happens especially often if you’re in the middle of a project that’s slowly being migrated over to SwiftUI.
Here’s a little NSView extension that may help:
import Cocoa import SwiftUI enum ViewAnchor { case top case left case bottom case right static let all: [ViewAnchor] = [.top, .left, .bottom, .right] } extension NSView { func constraintEdge(_ name: ViewAnchor, to: NSView) { switch(name) { case .top: self.topAnchor.constraint(equalTo: to.topAnchor).isActive = true case .left: self.leftAnchor.constraint(equalTo: to.leftAnchor).isActive = true case .bottom: self.bottomAnchor.constraint(equalTo: to.bottomAnchor).isActive = true case .right: self.rightAnchor.constraint(equalTo: to.rightAnchor).isActive = true } } public func addResizableSubview(_ other: NSView) { other.autoresizingMask = [.width, .height] self.autoresizesSubviews = true other.frame = NSRect(x: 0, y: 0, width: self.frame.width, height: self.frame.height) self.addSubview(other) } public func addResizingSubview(_ other: NSView) { addSubview(other) other.translatesAutoresizingMaskIntoConstraints = false for anchor in ViewAnchor.all { self.constraintEdge(anchor, to: other) } } } class ViewController: NSViewController { override func viewDidLoad() { super.viewDidLoad() let host = NSHostingController(rootView: YourSwiftUIView()) self.view.addResizableSubview(host.view) } }
Using this extension, you have two options to add the subview:
addResizingSubview (this will stretch the parent view to satisfy the size constraints of the subview)
addResizableSubview (this will make your subview respect the main view size)
As an added bonus, there’s a couple of little helpers for gluing view edges, using an enum for the edges instead of calling four separate constraints.
Hope this is as useful to others as it has been to me.
Leave a Reply