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