SwiftUI TextEditor - 编辑完成后保存状态
SwiftUI TextEditor - save the state after completion of editing
问题概述
我正在构建一个笔记应用程序,并且有一个笔记编辑视图,其中一些 TextEditor 用于收听用户的输入。现在一个环境对象被传递到这个笔记编辑视图,我设计了一个保存按钮来保存更改。它运行良好,除了用户必须单击保存按钮来更新模型。
预期行为
编辑完成后,文本编辑器应更新 EnvironmentObject 实例的值。不一定要点击保存按钮来保存修改。
下面是view的示例代码
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()
}
}
}
下面是EnvironmentObject编辑函数的示例代码
UserData.editPost(label: label!, id: id!, data: SingleNote(updateDate: Date(), title: title, body: content))
我尝试过的方法
- 我尝试向 TextEditor 添加 onChange 修饰符,但它会在发生任何更改时立即应用,这是不希望的。我还尝试了一些其他修饰符,如 onDisapper 等
- 用户数据有
@Published var NoteList: [String: [SingleNote]]
,我试图将 $UserData.NoteList[label][id].title 传递给 TextEditor,但也没有被接受
在网上没有找到很好的解决方案所以在这里提出这个问题。提前感谢您的建议!
我不明白编辑完成后保存的确切含义。这是我发现的两种可能的方法。
注意:
在下面的演示中,蓝色背景的文本显示保存的文本。
1。用户关闭键盘时保存
解决方案:添加点击手势,让用户在 TextEditor
之外点击时关闭键盘。同时调用save()
代码:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onTapGesture {}
}
.onTapGesture { hideKeyboardAndSave() }
}
private func hideKeyboardAndSave() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
save()
}
private func save() {
savedText = text
}
}
2。 x 秒无更改后保存
解决方案:使用 Combine
和 .debounce
仅在 x
秒后没有进一步的事件后发布和观察。
我已将 x
设置为 3。
代码:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
let detector = PassthroughSubject<Void, Never>()
let publisher: AnyPublisher<Void, Never>
init() {
publisher = detector
.debounce(for: .seconds(3), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onChange(of: text) { _ in detector.send() }
.onReceive(publisher) { save() }
}
}
private func save() {
savedText = text
}
}
问题概述
我正在构建一个笔记应用程序,并且有一个笔记编辑视图,其中一些 TextEditor 用于收听用户的输入。现在一个环境对象被传递到这个笔记编辑视图,我设计了一个保存按钮来保存更改。它运行良好,除了用户必须单击保存按钮来更新模型。
预期行为
编辑完成后,文本编辑器应更新 EnvironmentObject 实例的值。不一定要点击保存按钮来保存修改。
下面是view的示例代码
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()
}
}
}
下面是EnvironmentObject编辑函数的示例代码
UserData.editPost(label: label!, id: id!, data: SingleNote(updateDate: Date(), title: title, body: content))
我尝试过的方法
- 我尝试向 TextEditor 添加 onChange 修饰符,但它会在发生任何更改时立即应用,这是不希望的。我还尝试了一些其他修饰符,如 onDisapper 等
- 用户数据有
@Published var NoteList: [String: [SingleNote]]
,我试图将 $UserData.NoteList[label][id].title 传递给 TextEditor,但也没有被接受
在网上没有找到很好的解决方案所以在这里提出这个问题。提前感谢您的建议!
我不明白编辑完成后保存的确切含义。这是我发现的两种可能的方法。
注意: 在下面的演示中,蓝色背景的文本显示保存的文本。
1。用户关闭键盘时保存
解决方案:添加点击手势,让用户在 TextEditor
之外点击时关闭键盘。同时调用save()
代码:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onTapGesture {}
}
.onTapGesture { hideKeyboardAndSave() }
}
private func hideKeyboardAndSave() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
save()
}
private func save() {
savedText = text
}
}
2。 x 秒无更改后保存
解决方案:使用 Combine
和 .debounce
仅在 x
秒后没有进一步的事件后发布和观察。
我已将 x
设置为 3。
代码:
struct ContentView: View {
@State private var text: String = ""
@State private var savedText: String = ""
let detector = PassthroughSubject<Void, Never>()
let publisher: AnyPublisher<Void, Never>
init() {
publisher = detector
.debounce(for: .seconds(3), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}
var body: some View {
VStack(spacing: 20) {
Text(savedText)
.frame(width: 300, height: 200, alignment: .topLeading)
.background(Color.blue)
TextEditor(text: $text)
.frame(width: 300, height: 200)
.border(Color.black, width: 1)
.onChange(of: text) { _ in detector.send() }
.onReceive(publisher) { save() }
}
}
private func save() {
savedText = text
}
}