I have a macOS SwiftUI app with a secondary window that should be opened/displayed if a certain condition occurs. The logic that detects the condition is inside a Swift class.
I see lots of examples where opening a window is done inside another SwiftUI View using something like
struct ContentView: View {
@Environment(\.openWindow) var openWindow
var body: some View {
...
Button("Open window") {
openWindow(id: "secondWindowId")
}
}
In my case, the logic that detects the condition that would prompt the opening of secondWindowId is in a Swift class (not a SwiftUI View).
Is there a standard way to open the window identified with "secondWindowId" from inside a Swift class?
I found a solution to programmatically opening a window, but I don't know if it the most elegant. It is also a bit complicated. (I'm sorry, but I forgot the original author on the Internet to give them credit.)
(1) I changed the Window to a WindowGroup.
(2) That allowed me to add the .handlesExternalEvents() modifier. The scene now looks like:
struct NetworkAgentInstallScene: Scene {
var body: some Scene {
WindowGroup("Initial Install Agent", id: "installagentwindow") {
InstallAgentView()
}
.defaultSize(width: 400, height: 300)
.commandsRemoved()
.handlesExternalEvents(matching: Set(arrayLiteral: Wnd.InstallAgentView.rawValue))
}
}
(3) Wnd is an enum with the InstallAgentView as one of the types. This approach gives you the opportunity to open several different window types.
enum Wnd: String, CaseIterable {
case InstallAgentView = "InstallAgentView"
case OtherView = "OtherView"
func open(){
if let url = URL(string: "MyCompanyMyApp://\(self.rawValue)") {
os_log("opening \(self.rawValue)")
NSWorkspace.shared.open(url)
}
}
}
(4) I had to register the MyCompanyMyApp as a URL Type in the target's Info tab
(5) Then, in the Swift class, I could call open() on the enum type:
Wnd.InstallAgentView.open()
This allows me to open an appropriate window when my regular Swift code notices that the user needs to handle something that is controlled through the auxiliary window.