Hi
I am still studying Core Data by doing an application, but I hit a blocker.
Can some one help please? Here is the description of my issue:
I have 2 views: ManageProblemView and ProblemDetailView
When I do the edit operation, upon execution of viewContext.save(), I am getting extra blank problem instance on my storage.
During debugging, the issue occurred at MARK: Edit Operation second half
I tried to put breakpoint on
Initial View:
The summary of my edit flow is:
-
when user swipe list item and clicked edit button, the item will be save in optional var problemOnEdit
-
the application will then display ProblemDetailView (as popover) passing the value of the list item using an instance of a binded struct tempProblem. The value received will displayed in the TextField for editing.
-
After editing, the user will click save button, and the onDismiss edit branch will be executed (MARK: Edit Operation second half)
Expected result is: the edited value will be save
Actual result: the edited value do saved and reflected, but there is an extra blank item created and saved
What I tried prior to consultation:
-
Instead of passing the instance to edit, I just save the index of the target item on list for editing to a state variable integer. In the second half of editing, I directly access problems : FetchedResults element and edit with new value.
Result: same thing happened (extra element is saved) -
I removed the display of popover and hardcoded the editing
p.content = “edited…”
executed viewContext.save()
Result: element was replaced by “edited…” and no extra eminent was generated
I hope I can get a hand. I am just starting to learn swiftui.
Thank you.
//
// ManageProblemView.swift
// QuizPrototype
//
// Created by Michael Javier on 2/2/22.
//
import SwiftUI
struct ManageProblemView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(sortDescriptors: []) var problems : FetchedResults<Problem>
@State var tempProblem = ProblemDetail(value: "")
@State var searchValue : String = ""
@State var showModal : Bool = false
@State private var arrayIndex : Int = -1
@State var problemOnEdit : Problem?
var body: some View {
NavigationView {
VStack {
HStack{
TextField("Search Problem", text: $searchValue).padding(.leading)
.background(Capsule().stroke())
Spacer()
Button {
print("insert handler here")
} label: {
Image(systemName: "magnifyingglass")
}
}.padding()
Spacer()
List(problems) { p in
Text(p.content ?? "")
.swipeActions(allowsFullSwipe: false) {
//MARK: Delete Operation
Button {
viewContext.delete(p)
do {
try viewContext.save()
} catch {
}
} label: {
Label("Delete", systemImage: "minus.circle")
}
.tint(.red)
// MARK: Edit Operation first half
Button {
problemOnEdit = p
// p.content = "edited..."
// do {
// try viewContext.save()
//
// } catch {
// print(error)
// }
tempProblem.addMode = false
if let x = p.content {
tempProblem.content = x
}
// save index of p from problems
if let tmpArryIdx = problems.firstIndex(of: p) {
arrayIndex = tmpArryIdx
print(tmpArryIdx)
}
// display Modal for add/edit
showModal = true
} label: {
Label("Edit", systemImage: "pencil.circle")
}
.tint(.blue)
}
}.listStyle(.plain)
Button(action: {
tempProblem.content = ""
tempProblem.addMode = true
showModal = true }) {
Text("Add")
}
.padding()
.background(Capsule().stroke(lineWidth: 1))
.fullScreenCover(isPresented: $showModal, onDismiss: {
let p = Problem(context: viewContext);
if(tempProblem.addMode == true)
{
p.problemId = UUID()
p.content = tempProblem.content
do {
try viewContext.save()
}
catch
{
}
tempProblem.content = ""
}
else
{
// MARK: Edit Operation second half
let str = tempProblem.content.trimmingCharacters(in: .whitespacesAndNewlines)
if(arrayIndex > 0 && str != "")
{
if let pb = problemOnEdit {
pb.content = str
// save context
do {
try viewContext.save()
} catch {
print(error)
}
}
// return states and variable to its default value
tempProblem.content = ""
}
}
}, content: {
// let problemInstance = TeProblem()
ProblemDetailView(problemDetail: $tempProblem)
})
}.navigationTitle("Manage Problems")
.navigationBarTitleDisplayMode(.inline)
}
}
}
struct ManageProblemView_Previews: PreviewProvider {
static var previews: some View {
ManageProblemView()
}
}
for Problem Detail View:
//
// ProblemDetailView.swift
// QuizPrototype
//
// Created by Michael Javier on 2/9/22.
//
import SwiftUI
struct ProblemDetailView: View {
@Environment(\.presentationMode) var presentationMode
// @ObservedObject var problemDetail: TempProblem
@Binding var problemDetail: ProblemDetail
var body: some View {
NavigationView {
VStack {
TextField("Problem Entry", text: $problemDetail.content)
.padding()
.background(Rectangle().stroke(lineWidth: 1).padding())
Spacer()
if(problemDetail.addMode)
{
Text("Add")
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
else
{
Text("Save")
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
}
}
}
}
struct ProblemDetailView_Previews: PreviewProvider {
static var previews: some View {
ProblemDetailView(problemDetail: .constant(ProblemDetail(value: "Sample Problem")))
}
}