Reputation: 11
My goal is to save the contents only if the user taps "Save", but to discard the edits when they click "Cancel".
That's why I created two variables that receive the initial values of note.content
and note.title
.
Those are the ones that users will actually edit. My aim is to take the edited values and assign them to the note instance, which is what I want to edit, only when the user taps "Save".
However, this is not happening because when I tap "Save", note.content
and note.title
remain the same value as before and don't reflect the changes.
I don't know what else to do; if someone could help me with this, I would appreciate it.
struct EditNoteView: View {
@State var note: Note
@Environment(\.dismiss) var dismiss
@State var editedTitle: String
@State var editedContent: String
var body: some View {
NavigationStack {
VStack {
TextEditor(text: $editedTitle)
.font(.title)
.fontWeight(.bold)
.frame(width: UIScreen.main.bounds.width, height: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
Divider()
TextEditor(text: $editedContent)
.font(.body)
.frame(maxHeight:.infinity)
}
}
.navigationBarBackButtonHidden(true)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") {
dismiss()
}
}
ToolbarItem(placement: .topBarTrailing) {
Button("Save") {
note.title = editedTitle
note.content = editedContent
dismiss()
}
}
}
}
}
Upvotes: 1
Views: 277
Reputation: 20459
I would think you want to supply your editor with a Note
to be edited, then the supplied note is either updated or left unchanged when the view is dismissed, depending on which button was pressed. So the following changes are needed:
NavigationStack
. The navigation probably needs to be done outside of the editor, in other words, by a parent view.Binding
.State
variable for every property of a Note
. You just need a temporary copy of the whole Note
.VStack
of the editor, not to the NavigationStack
.TextEditor
is greedy and uses all the space available, so you don't need to give it maximum width or maximum height.Here is a revised version of your example with the changes applied:
struct Note {
var title: String
var content: String
}
struct EditNoteView: View {
@Binding private var note: Note
@State private var editedNote: Note
@Environment(\.dismiss) private var dismiss
init(note: Binding<Note>) {
self._note = note
self._editedNote = .init(initialValue: note.wrappedValue)
}
var body: some View {
VStack(alignment: .leading) {
TextEditor(text: $editedNote.title)
.font(.title)
.fontWeight(.bold)
.frame(height: 50)
Divider()
TextEditor(text: $editedNote.content)
.font(.body)
}
.padding(.horizontal, 12)
.toolbar {
ToolbarItem(placement: .topBarLeading) {
Button("Cancel") {
dismiss()
}
}
ToolbarItem(placement: .topBarTrailing) {
Button("Save") {
note = editedNote
dismiss()
}
}
}
}
}
struct ContentView: View {
@State private var note = Note(title: "Initial title", content: "Initial content")
var body: some View {
NavigationStack {
VStack {
VStack(alignment: .leading) {
Text(note.title)
.font(.title.bold())
.padding(.bottom)
Text(note.content)
}
.padding()
.border(.gray, width: 2)
.padding()
NavigationLink {
EditNoteView(note: $note)
.navigationBarBackButtonHidden(true)
} label: {
Label("Edit", systemImage: "pencil")
}
}
}
}
}
Hope that helps.
Upvotes: 2