How to open and dismiss windows in visionOS

Window Groups

Everything starts in the SwiftUI App file. When the app launches, a new window will be created using this window group and the ContentView.

import SwiftUI

@main
struct Garden01App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
A visionOS window with buttons to open and dismiss another window.

Let’s add another window group, this time with an id value.

import SwiftUI

@main
struct Garden01App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }

        WindowGroup(id: "YellowFlower") {
            YellowFlowerView()
        }
    }
}

Now we have a second window with an id “YellowFlower” which loads a view called YellowFlowerView.

Note: By default, the app will open the first WindowGroup. This is based on the order the groups appear in the App file.

Open Window

So how do we open our new window? First we retrieve openWindow from the environment. Then we can call this with an id to open an instance of this window: openWindow(id: "YellowFlower").

struct ContentView: View {

    @Environment(\.openWindow) var openWindow
    @Environment(\.dismissWindow) var dismissWindow

    var body: some View {
        VStack(spacing: 24) {
            Text("Window Garden 🌸")
                .font(.extraLargeTitle2)
            Text("Open and Close a window with an id value of `YellowFlower`")
            HStack {
                Button(action: {
                    openWindow(id: "YellowFlower")
                }, label: {
                    Label("Open Window", 
                    systemImage: "inset.filled.center.rectangle.badge.plus")
                })

                Button(action: {
                    dismissWindow(id: "YellowFlower")
                }, label: {
                    Label("Close Window", 
                    systemImage: "xmark.circle")
                })
            }
        }
        .padding()
    }
}
A new visionOS window in front of the previous one, with a button to close it.

Dismiss Window

Closing a window is very similar to opening one. We can add the dismissWindow environment value and call it to close a window by id. We could even add the close window button to the new window.

struct ContentView: View {

    @Environment(\.openWindow) var openWindow
    @Environment(\.dismissWindow) var dismissWindow

    var body: some View {
        VStack(spacing: 24) {
            Text("Window Garden 🌸")
                .font(.extraLargeTitle2)
            Text("Open and Close a window with an id value of `YellowFlower`")
            HStack {
                Button(action: {
                    openWindow(id: "YellowFlower")
                }, label: {
                    Label("Open Window", 
                    systemImage: "inset.filled.center.rectangle.badge.plus")
                })

                Button(action: {
                    dismissWindow(id: "YellowFlower")
                }, label: {
                    Label("Close Window", 
                    systemImage: "xmark.circle")
                })
            }
        }
        .padding()
    }
}

Demo 01 – Opening and closing the window

visionOS simulator screenshot showing a window. A user taps a button to open a new window, then closes it.

Demo 02 – Closing multiple windows with the same id value

visionOS simulator screenshot showing a window. A user taps a button to open multiple instances of a new window.

You should be aware of some important details here. We can tap the open window button as many times as we like, opening multiple instances of the new window. But when we tap the close window button, all windows with an id that matches our value will be closed at the same time.

Sample code is available in Garden01 in Step Into Example Projects

Support our work so we can continue to bring you new examples and articles.

Download the Xcode project with this and many more examples from Step Into Vision.
Some examples are provided as standalone Xcode projects. You can find those here.

Questions or feedback?

2 Comments

  1. Thanks for posting the sample code along with this. It must be a lot of work to set up a project for each of these posts!

    1. Thanks! It is a little extra work but I didn’t see another way when working with Windows. For smaller demos I can use a single Xcode project through. Anyway, we had to test the comment system somehow.