Please excuse me if I'm using the wrong nomenclature of things, but this is the first time I'm using CoreData. I'm editing text in one of the items stored using CoreData. The way it works on the app is when tapping on an item in a list, a sheet pops up with the text that is already there, and if changed, saves the new text.
I'm struggling with how to pass the correct item to the sheet, and then how to update the correct item. How do you do this? I'm not sure how passing data works.
Here's what I worked out so far:
struct ContentView: View {
@FetchRequest(entity: Jot.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Jot.date, ascending: false)])
var jots: FetchedResults<Jot>
@State var selectedJot: Jot
@State var isNew = false
var body: some View {
NavigationView {
List(jots) { jot in
Text(jot.text ?? "")
.onTapGesture() {
self.selectedJot = jot
isNew = false
}
}
.listStyle(.plain)
.toolbar {
ToolbarItem(placement: .bottomBar) {
Spacer()
}
ToolbarItem(placement: .bottomBar) {
Button(action: {
isNew = true
self.sheetNewNote.toggle()
selectedItem = 0
}) {
Image(systemName: "square.and.pencil")
}
}
}
.sheet(item: $selectedJot) { jot in
SheetView(isNewItem: $isNew, currJot: self.$selectedJot) // I get error Cannot convert value of type 'Binding<Jot>' to expected argument type 'Binding<Item?>'
}
.sheet(isPresented: $sheetNewNote) {
SheetView(isNewItem: $isNew, currJot: self.$selectedJot) // no error here
}
}
}
struct SheetView: View {
@Environment(\.presentationMode) var presentationMode
@Binding var isNewItem: Bool
@Binding var currJot: Jot
@State var text: String = ""
var body: some View {
NavigationView {
VStack {
TextEditor(text: $text)
.onAppear() {
if isNewItem {
text = currJot.text!
}
}
HStack {
Button("Cancel") {
presentationMode.wrappedValue.dismiss()
}
Spacer()
Button("Save") {
if isNewItem {
// create a new item and save it with try viewContext.save()
} else {
// we are editing a current item
updateJot(updatedJot: currJot)
try? viewContext.save()
}
presentationMode.wrappedValue.dismiss()
}
}
}
}
}
// Updates the item
func updateJot(updatedJot: Jot){
if let jot = getById(id: updatedJot.objectID){
jot.text = updatedJot.text
}
}
// Gets a item by id
func getById(id: NSManagedObjectID) -> Jot? {
return viewContext.object(with: id) as? Jot
}
}
}
EDIT:
trying to understand more about how CoreData and SwiftUI work. Based on the comment below, I should use @ObservableObject
but when I went looking for more information, I couldn't find any definitive examples.
This article also made even more confusing to me.
So, question still: how so I update an item already existing via a sheet
?
This, however, looks promising... I just need to understand what they did and see if I can replicate it on my code.