Dunfey · Hotel WWDC as data, est. 1983
Front desk everything
Years
Topics

2024 Spatial ComputingSwiftUI & UI Frameworks

WWDC24 · 13 min · Spatial Computing / SwiftUI & UI Frameworks

Work with windows in SwiftUI

Learn how to create great single and multi-window apps in visionOS, macOS, and iPadOS. Discover tools that let you programmatically open and close windows, adjust position and size, and even replace one window with another. We’ll also explore design principles for windows that help people use your app within their workflows.

Watch at developer.apple.com ↗

Transcript all transcripts

Chapters

Code shown on screen · 14 snippets

BOT-anist scenes swift · at 2:36 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        WindowGroup(id: "editor") {
            EditorContentView()
        }

        WindowGroup(id: "game") {
            GameContentView()
        }
        .windowStyle(.volumetric)
    }
}
Creating the movie WindowGroup swift · at 3:09 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        WindowGroup(id: "editor") {
            EditorContentView()
        }

        WindowGroup(id: "game") {
            GameContentView()
        }
        .windowStyle(.volumetric)

        WindowGroup(id: "movie") {
            MovieContentView()
        }
    }
}
Opening a movie window swift · at 3:55 ↗
struct EditorContentView: View {
    @Environment(\.openWindow) private var openWindow

    var body: some View {
        Button("Open Movie", systemImage: "tv") {
            openWindow(id: "movie")
        }
    }
}
Pushing a movie window swift · at 4:45 ↗
struct EditorContentView: View {
    @Environment(\.pushWindow) private var pushWindow

    var body: some View {
        Button("Open Movie", systemImage: "tv") {
            pushWindow(id: "movie")
        }
    }
}
Toolbar swift · at 5:34 ↗
CanvasView()
    .toolbar {
        ToolbarItem {
            Button(...)
        }
        ...
    }
Title menu swift · at 5:40 ↗
CanvasView()
    .toolbar {
        ToolbarTitleMenu {
            Button(...)
        }
        ...
    }
Hiding window controls swift · at 5:48 ↗
WindowGroup(id: "movie") {
    ...
}
.persistentSystemOverlays(.hidden)
Creating the controller window swift · at 6:28 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        ...

        WindowGroup(id: "movie") {
            MovieContentView()
        }

        WindowGroup(id: "controller") {
            ControllerContentView()
        }
    }
}
Opening the controller window swift · at 6:34 ↗
struct GameContentView: View {
    @Environment(\.openWindow) private var openWindow

    var body: some View {
        ...
        Button("Open Controller", systemImage: "gamecontroller.fill") {
            openWindow(id: "controller")
        }
    }
}
Positioning the controller window swift · at 7:46 ↗
WindowGroup(id: "controller") {
    ControllerContentView()
}
.defaultWindowPlacement { content, context in
    #if os(visionOS)
    return WindowPlacement(.utilityPanel)
    #elseif os(macOS)
    ...
    #endif
}
Positioning the controller window continued swift · at 8:45 ↗
WindowGroup(id: "controller") {
    ControllerContentView()
}
.defaultWindowPlacement { content, context in
    #if os(visionOS)
    return WindowPlacement(.utilityPanel)
    #elseif os(macOS)
    let displayBounds = context.defaultDisplay.visibleRect
    let size = content.sizeThatFits(.unspecified)
    let position = CGPoint(
        x: displayBounds.midX - (size.width / 2),
        y: displayBounds.maxY - size.height - 20
    )
    return WindowPlacement(position, size: size)
    #endif
}
Default size swift · at 10:12 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        ...
        WindowGroup(id: "movie") {
            MovieContentView()
        }
        .defaultSize(width: 1166, height: 680)
    }
}
Setting resize limits on the movie window swift · at 10:49 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        ...
        WindowGroup(id: "movie") {
            MovieContentView()
                .frame(
                    minWidth: 680, maxWidth: 2720,
                    minHeight: 680, maxHeight: 1020
                )
        }
        .windowResizability(.contentSize)
    }
}
Controller window resizability swift · at 11:37 ↗
@main
struct BOTanistApp: App {
    var body: some Scene {
        ...
        WindowGroup(id: "controller") {
            ControllerContentView()
        }
        .windowResizability(.contentSize)
    }
}

Resources