I've got a Mac Document App using SwiftUI and SwiftData.
All is working well with the models editing, etc.
There's a feature I need to implement, and can't seem to make it work.
From the main window of the app, I need to be able to launch an auxilliary window containing a view-only representation of the model being edited. The required workflow is something like this:
Open a document (SwiftData)
Select a sub-model of the document
Launch the aux window to display the view of the model data (must be in a separate window, because it will be on a different physical display)
Continue making edits to the sub-model, as they are reflected in the other window
So, below is the closest I've been able to come, and it's still not working at all. What happens with this code:
Click on the "Present" button, the encounter-presentation Window opens, but never loads the data model or the view. It's just an empty window.
This is the spot in the main view where the auxiliary window will be launched:
@State
var presenting: Presentation? = nil
var presentingThisEncounter: Bool {
presenting?.encounter.id == encounter.id
}
@Environment(\.openWindow) var openWindow
...
if presentingThisEncounter {
Button(action: { presenting = nil }) {
Label("Stop", systemImage: "stop.fill")
.padding(.horizontal, 4)
}
.preference(key: PresentationPreferenceKey.self, value: presenting)
} else {
Button(action: {
presenting = Presentation(encounter: encounter, display: activeDisplay)
openWindow(id: "encounter-presentation")
}) {
Label("Present", systemImage: "play.fill")
.padding(.horizontal, 4)
}
.preference(key: PresentationPreferenceKey.self, value: nil)
}
Presentation is declared as:
class Presentation: Observable, Equatable {
Here's the contents of the App, where the DocumentGroup & model is instantiated, and the aux window is managed:
@State
var presentation: Presentation?
var body: some Scene {
DocumentGroup(editing: .encounterList, migrationPlan: EncounterListMigrationPlan.self) {
ContentView()
.onPreferenceChange(PresentationPreferenceKey.self) { self.presentation = $0 }
}
Window("Presentation", id: "encounter-presentation") {
VStack {
if let presentation = presentation {
PresentingView(presentation: presentation)
}
}
}
}
And the definition of PresentationPreferenceKey:
struct PresentationPreferenceKey: PreferenceKey {
static var defaultValue: Presentation?
static func reduce(value: inout Presentation?, nextValue: () -> Presentation?) {
value = nextValue()
}
}