Last active
March 21, 2024 21:24
-
-
Save JetForMe/470be5a57bd690af370785a88e4f7b16 to your computer and use it in GitHub Desktop.
Dealing with @bindable Being Non-Optional
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
The idea is to be able to invoke `ReminderDetailsWrapper` (forgive the naming, it’s | |
the result of the organic growth of this thing) with either the ID of an object to edit, | |
or nil, in which case it will create a new one. In both cases, it has to create a new | |
`ModelContext` on which to make the changes, and it only saves if the user taps the | |
“Save” button. | |
Some of thie could be improved if things could be loaded in `init()`, but that gets | |
called far too often as SwiftUI rebuilds the view hierarchy. | |
*/ | |
struct | |
ReminderDetailsWrapper : View | |
{ | |
let reminderToEdit : PersistentIdentifier? | |
var | |
body: some View | |
{ | |
Group | |
{ | |
if let reminder = self.reminder, | |
let context = self.editContext | |
{ | |
ReminderDetailsView(reminder: reminder) | |
.modelContext(context) | |
} | |
else | |
{ | |
EmptyView() | |
} | |
} | |
.onAppear | |
{ | |
do | |
{ | |
// Create a context in which to work… | |
self.editContext = ModelContext(self.modelContext.container) | |
self.editContext?.undoManager = UndoManager() | |
// If ``reminderToEdit`` is not nil, load it, | |
// otherwise, create a new one… | |
if let reminderID = self.reminderToEdit | |
{ | |
self.reminder = self.editContext!.registeredModel(for: reminderID) | |
} | |
else | |
{ | |
self.reminder = try self.model.newReminder(in: self.editContext!) | |
} | |
} | |
catch | |
{ | |
print("Unable to load or create new reminder: \(error.localizedDescription)") | |
} | |
} | |
} | |
@State private var editContext : ModelContext? | |
@State private var reminder : CMReminder? | |
@EnvironmentObject private var model : CMModel | |
@Environment(\.modelContext) private var modelContext | |
} | |
struct | |
ReminderDetailsView: View | |
{ | |
@Bindable var reminder : CMReminder | |
var | |
body: some View | |
{ | |
NavigationStack | |
{ | |
EditReminderForm(reminder: self.reminder) | |
.navigationTitle(Text("Set Reminder")) | |
.toolbar | |
{ | |
ToolbarItem(placement: .navigationBarLeading) | |
{ | |
Button("Close", action: close) | |
} | |
ToolbarItem(placement: .navigationBarTrailing) | |
{ | |
Button("Save", action: save) | |
} | |
} | |
.interactiveDismissDisabled(self.isModified) | |
.confirmationDialog("Discard Changes?", isPresented: self.$isPresentingConfirmation) | |
{ | |
Button("Discard", role: .destructive) { self.dismiss() } | |
Button("Keep Editing", role: .cancel) { } | |
} | |
} | |
} | |
func | |
close() | |
{ | |
if self.isModified | |
{ | |
self.isPresentingConfirmation = true | |
} | |
else | |
{ | |
self.dismiss() | |
} | |
} | |
func | |
save() | |
{ | |
Task | |
{ | |
do | |
{ | |
try await self.model.register(reminder: self.reminder) | |
try self.modelContext.save() | |
self.dismiss() | |
} | |
catch | |
{ | |
print("Unable to save reminder changes: \(error.localizedDescription)") | |
// TODO: Display an error alert | |
} | |
} | |
} | |
@Query(sort: \CMVehicle.name) private var vehicles : [CMVehicle] | |
private var isModified : Bool { self.modelContext.undoManager!.canUndo } | |
@State private var isPresentingConfirmation = false | |
@EnvironmentObject private var model : CMModel | |
@Environment(\.modelContext) private var modelContext | |
@Environment(\.dismiss) private var dismiss | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment