Need suggestions on publisher autosave solutions

Background


I am building a note taking app and there is a note editing view where a few SwiftUI TextEditors are used to listen to users' input. Right now an environment object is passed to the this note editing view and I designed a save button to save the change. It works well except that users have to click the save button to update the model. The function is exactly like what Apple has done with the native note app.

Expected behaviors


The text editor is expected to update the value of instances of the EnvironmentObject once any editing happens. Do not necessarily click the save button to save the changes.

Sample code

Code Block swift
struct NoteDetails: View {
@EnvironmentObject var UserData: Notes
@Binding var selectedNote: SingleNote?
@Binding var selectedFolder: String?
@Binding var noteEditingMode: Bool
@State var title:String = ""
@State var updatedDate:Date = Date()
@State var content: String = ""
var id: Int?
var label: String?
@State private var wordCount: Int = 0
var body: some View {
VStack(alignment: .leading) {
TextEditor(text: $title)
.font(.title2)
.padding(.top)
.padding(.horizontal)
.frame(width: UIScreen.main.bounds.width, height: 50, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/)
Text(updatedDate, style: .date)
.font(.subheadline)
.padding(.horizontal)
Divider()
TextEditor(text: $content)
.font(.body)
.lineSpacing(15)
.padding(.horizontal)
.frame(maxHeight:.infinity)
Spacer()
}
}
}


Below is the sample code of edit func of the EnvironmentObject


Code Block swift
UserData.editPost(label: label!, id: id!, data: SingleNote(updateDate: Date(), title: title, body: content))


Ways I have tried without luck

  • I tried to add a onChange modifier to the TextEditor but it applies as soon as any change happens, which is not desired. I also tried a few other modifiers like onDisapper etc.

  • User data has @Published var NoteList: [String: [SingleNote]] and I tried to pass the $UserData.NoteList[label][id].title in to the TextEditor and it was not accepted either


Did not find sound solutions in the Internet so bring up this question here. Thanks for suggestions in advance!

The text editor is expected to update the value of instances of the EnvironmentObject once any editing happens.

it applies as soon as any change happens, which is not desired

Seems your description is inconsistent. Please specify when do you want to save clearly.
@OOPer, the behavior of TextEditor is expected, but as you see, I created a @State variable to store the input of Users so I need to update the instance of EnvironmentObject with the @State variable . I tried to put the instance of EnvironmentObject directly into the TextEditor but it cannot compile with an error:

Code Block
Failed to produce diagnostic for expression; please file a bug report


Code Block swift
TextEditor(text: $UserData.NoteList[label ?? ""][id ?? 0].title ?? $title)
                    .font(.title2)
                    .padding(.top)
                    .padding(.horizontal)
                    .frame(height: 50, alignment: .center)

Please specify when do you want to save

Can you please answer to my question?
It should save as soon as anything changes, that is autosave I meant.

It should save as soon as anything changes, that is autosave I meant.

Thanks. Then this description

I tried to add a onChange modifier to the TextEditor but it applies as soon as any change happens, which is not desired.

is sort of a mistake, OK? applies as soon as any change happens is the desired behavior.
I should have put more context here. Thanks for the suggestions.

I tried .onChange modifier:
Code Block swift
.onChange(of: content, perform: { value in
                        UserData.editPost(label: label!, id: id!, data: SingleNote(updateDate: Date(), title: title, body: value))
                    })


It works to some extent if I type in something, it should update the instance of EnvironmentObject. But what is weird is, this editing view is a child view of a navigation link. Whenever I type in something, the changes have been made to the EnvironmentObject and the parent view gets refreshed. So the current view dismisses as a result and I was pushed to the parent navigation view.

Intuitively, every time I type in something with the onChange solution, the changes happen and I get pushed to the parent view since the model in the parent view gets refreshed.

I should have put more context here.

Please clarify:
  • applies as soon as any change happens is the desired behavior

  • but with using onChange, you find some undesired behavior

Is that OK?

You should better show all the view hierarchy and all the definitions of relevant types (Notes, SingleNote, or there may be more) to examine what is happening.
Need suggestions on publisher autosave solutions
 
 
Q