I'm currently developing an application using CoreData in SwiftUI.
I want to show a value from CoreData Entity as a state variable after I edit that data.
When I add a value as a new date I can show that value well, but after I edit the value it doesn't reflect the editing...
If I don't use @State, the value can be shown well, even after I edit it. But I need to use as @State value to bind it to a child view.
How could I solve this problem?
(I want to show the collect value after editing in a place I comment out as B same as like A in ListView.swift )
CDTest.xcdatamodeld
CDTestApp.swift
import SwiftUI
@main
struct CDTestApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
}
}
}
ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
ListView()
}
}
PersistenceController.swift
import CoreData
struct PersistenceController {
static let shared = PersistenceController()
let container: NSPersistentContainer
init(inMemory: Bool = false) {
container = NSPersistentContainer(name: "CDTest")
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
})
}
}
HomeViewModel.swift
import SwiftUI
import CoreData
class HomeViewModel :ObservableObject{
@Published var content = ""
//for newdata sheet
@Published var isNewDate = false
//storing update Item
@Published var updateItem : Task!
func writeData(context : NSManagedObjectContext){
if updateItem != nil {
updateItem.content = content
try! context.save()
updateItem = nil
isNewDate.toggle()
content = ""
return
}
let newTask = Task(context: context)
newTask.content = content
do{
try context.save()
isNewDate.toggle()
content = ""
}catch{
print(error.localizedDescription)
}
}
func EditItem(item:Task){
updateItem = item
content = item.content!
isNewDate.toggle()
}
}
ListView.swift
import SwiftUI
import CoreData
struct ListView: View {
@StateObject var homeData = HomeViewModel()
@FetchRequest(entity: Task.entity(), sortDescriptors: [NSSortDescriptor(key:"date",
ascending:true)],animation:.spring()) var results:FetchedResults<Task>
@Environment(\.managedObjectContext) var context
var body: some View {
NavigationView{
VStack(spacing:0){
//Empty View...
if results.isEmpty{
Text("NO Data")
}else{
LazyVStack{
ForEach(results){task in
VStack(alignment: .leading, spacing: 5, content: {
Text(task.content ?? "") // A
ListRow(content: task.content ?? "") // B
})
.contextMenu{
Button(action: {
homeData.EditItem(item: task)
}, label: {
Text("Edit")
})
Button(action: {
context.delete(task)
try! context.save()
}, label: {
Text("Delete")
})
}
}
}
.padding()
}
//Add Button...
Button(action: {homeData.isNewDate.toggle()}, label: {
Image(systemName: "plus")
.font(.largeTitle)
.padding()
})
.sheet(isPresented: $homeData.isNewDate, content: {
NewDataView(homeData: homeData)
})
}
}
}
}
ListRow.swift
import SwiftUI
struct ListRow: View {
@State var content:String
var body: some View {
Text(content)
NavigationLink(destination:DetailView(content: $content)){
Text("DETAIL")
}
}
}
DetailView.swift
import SwiftUI
struct DetailView: View {
@Binding var content:String
var body: some View {
Text(content)
}
}
NewDataView.swift
import SwiftUI
struct NewDataView: View {
@ObservedObject var homeData : HomeViewModel
@Environment(\.managedObjectContext) var context
var body: some View {
VStack{
Text("\(homeData.updateItem == nil ? "Add New" : "Up date")Task")
.font(.title)
TextEditor(text: $homeData.content)
.padding()
//Add Button...
Button(action: {homeData.writeData(context: context)}, label: {
Text(homeData.updateItem == nil ? "Add Now" : "Update")
.font(.title)
.fontWeight(.bold)
})
.padding()
.disabled(homeData.content == "" ? true : false)
.opacity(homeData.content == "" ? 0.5 : 1)
}
}
}
Xcode: Version 12.0.1
iOS: 14.0
Life Cycle: SwiftUI App
