For the sake of my research work at Postman, I get used to playing with Objective-C most of the time (due to full C++ interoperability). Recently, while crafting a new article on macOS internals (using SwiftUI), I encountered a unique challenge: setting a fixed window size for all users.
I quickly looked on the internet for solutions, but nothing I found hit the mark. Then, I tried to figure it out by myself using the documentation, Xcode, and my love for experimentation.
In this post, I’ll share the technique I used to constrain the size of a macOS application using SwiftUI.
Introduction
SwiftUI, Apple’s innovative UI toolkit, allows clean and efficient coding. However, setting up window size constraints was a bit tricky for me. Luckily, I’ve found a straightforward solution.
First try
I try to match minWidth
and minHeight
with maxWidth
and maxHeight
:
WindowGroup {
ContentView()
.frame(minWidth: 500,
maxWidth: 500,
minHeight: 300,
maxHeight: 300)
}
Naively, I thought that it could work, but…
The application is still resizable.
Explanation
Let’s go back to what it is to understand why it doesn’t work. This ContentView
is nothing more than a View
. To understand it better, let’s add an overlay:
WindowGroup {
ContentView()
.frame(minWidth: 500,
maxWidth: 500,
minHeight: 300,
maxHeight: 300)
.overlay(
RoundedRectangle(cornerRadius: 5)
.stroke(.gray, lineWidth: 1))
}
We clearly understand that this View has nothing to do with the window itself.
Adding a border to the ContentView helps us to understand the issue.
Once I realized this, I understood that there are two potential solutions for this:
- Find a way to add a fixed size to the WindowGroup
- Make the WindowGroup stick to the View size
As I’m not familiar with SwiftUI APIs, let’s try to explore available APIs.
How to disable resizability?
For the first one, I explored the list of potential modifiers in Xcode, and then I notified a .defaultSize(width:height:)
- I could use it like this:
.defaultSize(width: 500, height: 300)
Unfortunately, it won’t be the solution as the documentation said:
The size that you specify acts only as a default for when the window first appears. People can later resize the window using interface controls that the system provides.
Apple Developer DocumentationSets a default width and height for a window.
Now that I’m continuing to scroll into the list of available modifiers, I found this one:
With windowResizability
API, you can specify a strategy for the resizability of the window. For instance, you use the .contentSize
strategy:
WindowGroup {
ContentView()
.frame(minWidth: 500,
maxWidth: 500,
minHeight: 300,
maxHeight: 300)
}
.windowResizability(.contentSize)
A window resizability that’s derived from the window’s content.
🎉 TADA.
The window is not resizable anymore.