Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Resizing NSWindow to match view controller size in storyboard

I am working on Xcode 6.1.1 on OSX 10.10. I am trying out storyboards for Mac apps. I have a NSTabViewController using the new NSTabViewControllerTabStyleToolbar tabStyle and it is set as the default view controller for the window controller. How do I make my window resize according to the current selected view controller?

Is it possible to do entirely in Interface Builder? Here is what my storyboard looks like: storyboard

like image 862
Kaunteya Avatar asked Dec 20 '14 07:12

Kaunteya


Video Answer


2 Answers

The auto layout answer is half of it. You need to set the preferredContentSize in your ViewController for each tab to the fitting size (if you wanted the tab to size to the smallest size satisfying all constraints).

override func viewWillAppear() {
        super.viewWillAppear()
        preferredContentSize = view.fittingSize
}

If your constraints are causing an issue below try first with a fixed size, the example below sets this in the tab item's view controller's viewWillAppear function (Swift used here, but the Objective-C version works just as well).

override func viewWillAppear() {
        super.viewWillAppear()
        preferredContentSize = NSSize(width: 400, height: 280)
}

If that works, fiddle with your constraints to figure out what's going on

like image 68
rougeExciter Avatar answered Sep 23 '22 20:09

rougeExciter


The window containing a toolbar style tab view controller does resize without any code if you have auto layout constraints in your storyboard tab views (macOS 11.1, Xcode 12.3). I haven't tried other style tab view controllers.

If you want to resize with animation as in Finder, it is sufficient to add one override in your tab view controller. It will resize the window with system-calculated resize animation time and will hide the tab view during resize animation:

class PreferencesTabViewController: NSTabViewController {

    override func transition(from fromViewController: NSViewController, to toViewController: NSViewController, options: NSViewController.TransitionOptions = [], completionHandler completion: (() -> Void)? = nil) {

        guard let window = view.window else {
            super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
            return
        }

        let fromSize = window.frame.size
        let toSize = window.frameRect(forContentRect: toViewController.view.frame).size
        let widthDelta = toSize.width - fromSize.width
        let heightDelta = toSize.height - fromSize.height
        var toOrigin = window.frame.origin
        toOrigin.x += widthDelta / 2
        toOrigin.y -= heightDelta
        let toFrame = NSRect(origin: toOrigin, size: toSize)

        NSAnimationContext.runAnimationGroup { context in
            context.duration = window.animationResizeTime(toFrame)
            view.isHidden = true
            window.animator().setFrame(toFrame, display: false)
            super.transition(from: fromViewController, to: toViewController, options: options, completionHandler: completion)
        } completionHandler: { [weak self] in
            self?.view.isHidden = false
        }

    }

}

Please adjust closure syntax if you are using Swift versions older than 5.3.

like image 34
stasswtf Avatar answered Sep 22 '22 20:09

stasswtf