I have notes app using SwiftData also using CloudKit and the note editor is taking 125% CPU usage.
For example this is the note model:
@Model Class Note {
var title: String = ""
var content: String = ""
var creationDate: Date = Date.now
init(title: String = "", content: String = "") {
self.title = title
self.content = content
self.creationDate = Date.now
}
}
This is the NoteListView
struct NotesListView: View {
@Query(sort: [
SortDescriptor(\Note.creationDate, order: .reverse)
]) private var notes: [Note]
@Binding var selection: Set<Note.ID>
var body: some View {
List(selection: $selection) {
ForEach(notes) { note in
NavigationLink(value: note) {
NoteRowCell(note: note)
}
}
}
}
init(sort: SortDescriptor<Note>, searchString: String, selection: Binding<Set<Note.ID>>) {
_notes = Query(filter: #Predicate {
if searchString.isEmpty {
return true
} else {
return $0.content.localizedStandardContains(searchString)
}
}, sort: [sort])
_selection = selection
}
}
This is the ContentView:
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var sortOrder = SortDescriptor(\Note.creationDate, order: .reverse)
@State private var isShowingSearch = false
@State private var searchText = ""
@State private var path = [Note]()
@State private var selection = Set<Note.ID>()
var body: some View {
NavigationStack(path: $path) {
NotesListView(
sort: sortOrder,
searchString: searchText,
selection: $selection
)
.navigationDestination(for: Note.self) { note in
NoteEditorView(note: note)
}
.toolbar {
Button("Add Note") {
let note = Note()
modelContext.insert(note)
path = [note]
}
}
.searchable(
text: $searchText,
isPresented: $isShowingSearch,
prompt: "Search"
)
}
}
This is the NoteEditor:
struct NoteEditor: View {
@Bindable var note: Note // I guess this is the problem
var body: some View {
VStack {
TextField("Note title", text: $note.title)
Divider()
TextEditor(text: $note.content)
}
.padding(.horizontal, 25)
}
}
Typing to this literally takes 125% CPU usage. I assume that is because I am writing directly to SwiftData. Some kind of delay saving will solve this I guess. I tried but it isn't working.
NoteEditorand what you pass to it, eg, is it coming from a@Query var ...? You could be correct with your comment@Bindable var note: Note // I guess this is the problem.@State private var title: String = ""and then assign them inonAppearliketitle = note.titleand then do the opposite inonDisappear,note.title = titleand of course this should be done for all the properties. This way when you change your properties all changes will be local to the view and the edited Note object will only be changed when you leave the view which mean the@Querywill only update itself once.letinstead of@Bindable varfor thenoteproperty and that worked fine although it seems to work fine also without this change. And if it wasn't clear from my previous comment the 125% CPU usage you saw was from the query executing for basically every change (keystroke) in the editor view.onDisappearis not for this kind of scenario I guess or maybe I am missing something Edit: I solved this.onReceive(NotificationCenter.default.publisher(for: UIApplication.willResignActiveNotification)) { _ in saveNote() }