Tutorial "Working with UI Controls" EditButton already shows "Done"

In Section 4, step 1, we're instructed to add a button on the left to show "Done" while edit mode is active. However the EditButton control already changes its text between Edit and Done based on the mode. What that control lacks is a way to perform an action when the mode changes. I can follow the tutorial and add the extra button on the left, but that's not right for production code. What should be done in that situation?


https://developer.apple.com/tutorials/swiftui/working-with-ui-controls


HStack { 
  if self.mode?.value == .active {
    Button(action: { 
     self.profile = self.draftProfile // This action line needs to execute when (either) "Done" is tapped
     self.mode?.animation().value = .inactive 
    }) { 
      Text("Done")
    }
  }
  Spacer()
  EditButton() // This already will toggle between "Edit" and "Done" labels
}

I can offer this expanding on what you ask.


When using the EditButton(), I don't see how the tutorial intends for the ProfileSummary to ever be dismissed, nor for how the updated (or not) profile be incorporated into the running app. Some significant linkage seems missing from the architecture of the tutorial.


So, rather than the EditButton and the corresponding HStack, I'm trying using a NavigationView, but I can't get it right on passing back the changed / unmodified values. I'm not using a view that displays the existing values and offers an Edit button; instead I'm planning on the usual Cancel/Done setup and only an editor view.


I have this code:


struct SettingsHost: View {
    @ObservedObject var truth: Truth
    @Binding var showingSettings: Bool
    @State var savedSettings = SettingsValues()
    @State var draftSettings = SettingsValues()
    
    func performCancel() {
        self.draftSettings = self.savedSettings
        self.truth.settings = AppSettings(settings: self.savedSettings)
        self.$showingSettings.value.toggle()
    }

    func performDone() {
        self.savedSettings = self.draftSettings
        self.truth.settings = AppSettings(settings: self.draftSettings)
        self.$showingSettings.value.toggle()
    }

    
    var body: some View {
        return NavigationView {
            SettingsEditor(settings: $draftSettings)
            .font(.caption)
                .navigationBarTitle(Text("Settings"))
                .navigationBarItems(leading: Button(action: performCancel, label: {Text("Cancel")}),
                                    trailing: Button(action: performDone, label: {Text("Done")}))
        }
        .padding()
    }
}


In there, SettingsValues is a struct that mirrors the vars in AppSettings (a class); AppSettings persists itself to the UserDefaults.


The SettingsHost views and disappears as I expect (there's a


.sheet(isPresented: $showingSettings, onDismiss: {self.$showingSettings.value = false})


attached to a surrounding NavigationView; a button in there turns on showingSettings.


What I can't make work is whether the edited SettingsValues or the unmodified ones are present when showingSettings gets turned off. Specifically, whether I hit Done or Cancel, the modified values are what come up the next time I open SettingsHost -- the Cancel button doesn't work.

Tutorial "Working with UI Controls" EditButton already shows "Done"
 
 
Q