SwiftUI TextEditor bound to $[Note].content — slow performance?

  Kiến thức lập trình

I’m building simple text editor, which can handle several opened files. I have NotesManager, which stores all opened documents, and I pass binding to each of these notes to views using NavigationLink.

For some reason text field updates very slow on fast inserts even on small files (like 20 lines).

  1. Is it supposed to work so slowly or I’m missing some tagging // lazy updates approach?
  2. If it’s SwiftUI limitation, should I use AppKit without reactive binding to archieve desired performance?

NotesManager.swift

class NotesManager: ObservableObject {
    @Published var notes: [Note] = []
    
    var fileMonitors: [UUID: DispatchSourceFileSystemObject] = [:]

    func add(note: Note) {
        notes.append(note)
        monitorFile(for: note)
    }

    private func monitorFile(for note: Note) {
        ...
    }

    private func loadFileContent(for note: Note) {
        ...
        add(note)
    }
    
    ...
}

ContentView.swift

struct ContentView: View {
    @State private var selectedNoteID: UUID?
    @EnvironmentObject var notesManager: NotesManager
    
    var body: some View {
        NavigationSplitView {
            List($notesManager.notes, selection: $selectedNoteID) { $note in
                NavigationLink(destination: {
                    TextEditorView(note: $note)
                        .frame(minWidth: 400, maxWidth: .infinity, minHeight: 400, maxHeight: .infinity)
                }) {
                    SidebarItemView(note: note, selectedNoteID: $selectedNoteID)
                        .tag(note.id)
                }
            }
            .id(UUID())
        } detail: {
            Text("Open document to get started")
        }
    }
}

TextEditorView.swift

// Using CodeEditorView package

struct TextEditorView: View {
    @Binding var note: Note
    @State var text: String = ""
    @State var searchQuery: String = ""
    @State private var messages: Set<TextLocated<Message>> = Set ()
    @State private var editPosition: CodeEditor.Position = CodeEditor.Position()
    
    var body: some View {
        VStack {
            CodeEditor(text: $note.content, position: $editPosition, messages: $messages, language: .swift())
                .tag(note.id)
//                  .environment(.codeEditorTheme, colorScheme == .dark ? Theme.defaultDark : Theme.defaultLight)
        }
        
    }
}

LEAVE A COMMENT