From a “controller” window, I want to dynamically change the default size of a secondary window. Environment Objects do not work, because they aren’t instantiated when the App class is called:
import SwiftUI
@main
struct WindowSizeTestApp: App {
@Environment(.dismissWindow) private var dismissWindow
var body: some Scene {
WindowGroup {
ContentView()
}
.defaultSize(CGSize(width: 300, height: 300))
WindowGroup ("Second", id: "second") {
SecondView()
}
.defaultSize(CGSize(width: Singleton.shared.windowWidth, height: 300))
}
}
So my work-around was to create a singleton, such as this:
import Foundation
class Singleton: ObservableObject {
static let shared = Singleton()
@Published var windowWidth: Double = 800.0
func setWidth (width: Double) {
windowWidth = width
}
}
This works for getting the initial value (800) but doesn’t work when the value is modified.
import SwiftUI
struct ContentView: View {
@Environment(.supportsMultipleWindows) private var supportsMultipleWindows
@Environment(.openWindow) private var openWindow
@Environment(.dismissWindow) private var dismissWindow
@State private var width: Double = 100.0
var body: some View {
VStack {
Text("Width: (Int(width))")
.padding()
Slider(value: $width, in: 100...500, step: 1)
.padding()
.onChange(of: width) { newValue, oldValue in
Singleton.shared.setWidth(width: newValue)
}
Button(action: {
dismissWindow(id: "second")
openWindow(id: "second")
}) {
VStack {
Text("Open Window")
.font(.caption)
}
}
.padding()
.buttonStyle(PlainButtonStyle())
}
.padding()
}
}
The second window I have is just some default text like this:
import SwiftUI
struct SecondView: View {
var body: some View {
Text("Ere I am JH")
}
}
Is there a way to update a value and “redraw” or force a re-rendering of the windowgroups in an App class?
You can update and persist the desired sizes for the second WindowGroup
by adding an EnvironmentVariable
for width and for height.
On visionOS, you can’t force-resize an existing window, though.