Learn more about Russian war crimes in Ukraine.

Why is the contentRect of my NSWindow ignored?

When creating an NSWindow, you can pass a contentRect to set its size and position. But for me, the size and position were being ignored. The culprit was a call to setFrameAutosaveName. Here I describe what setFrameAutosaveName does, since it has no documentation.

Create a new macOS app in Xcode, and it will give you some Swift like this:

var window = NSWindow(
    contentRect: NSRect(x: 0, y: 0, width: 480, height: 300),
    styleMask: [.titled, .closable, .miniaturizable, .resizable, .fullSizeContentView],
    backing: .buffered, defer: false)
window.center()
window.setFrameAutosaveName("Main Window")
window.contentView = NSHostingView(rootView: contentView)
window.makeKeyAndOrderFront(nil)
}

The window it gives you can be resized and repositioned with the mouse. But try playing around with the contentRect: NSRect(x: 0, y: 0, width: 480, height: 300), and you’ll find that the values are stubbornly ignored! There are a couple of reasons for this.

The first reason is the call to window.center(). This changes the position of the window to be centered on the display, so your earlier x and y values are effectively ignored. But removing window.center() still won’t fix the issue.

The second, more interesting reason is the call to window.setFrameAutosaveName("Main Window"). There are no docs for setFrameAutosaveName, but here’s what it does. When the user moves or resizes a window that has an autosave name, the size and position are saved to the user defaults under that autosave name. Then when a window is created with an autosave name, if a size and position have been saved to user defaults, these preferences override the contentRect passed in the constructor. Here you can see the defaults after I moved and resized my "Main Window" window:

$ defaults read baz.ContentRectTest
{
    "NSWindow Frame Main Window" = "565 282 680 600 0 0 1680 1027 ";
}

The format here seems to be:

"NSWindow Frame \(autosaveName)" = "\(window.frame.x) \(window.frame.y) \(window.frame.width) \(window.frame.height) \(screen.x) \(screen.y) \(screen.width) \(screen.height - menuBar) ";

I don’t know why it also saves the details of the screen.

What can computers do? What are the limits of mathematics? And just how busy can a busy beaver be? This year, I’m writing Busy Beavers, a unique interactive book on computability theory. You and I will take a practical and modern approach to answering these questions — or at least learning why some questions are unanswerable!

It’s only $19, and you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

After months of secret toil, I and Andrew Carr released Everyday Data Science, a unique interactive online course! You’ll make the perfect glass of lemonade using Thompson sampling. You’ll lose weight with differential equations. And you might just qualify for the Olympics with a bit of statistics!

It’s $29, but you can get 50% off if you find the discount code ... Not quite. Hackers use the console!

More by Jim

Tagged #programming. All content copyright James Fisher 2020. This post is not associated with my employer. Found an error? Edit this page.