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))

我尝试过的方法

在网上没有找到很好的解决方案所以在这里提出这个问题。提前感谢您的建议!

我不明白编辑完成后保存的确切含义。这是我发现的两种可能的方法。

注意: 在下面的演示中,蓝色背景的文本显示保存的文本。

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
    }
}