Hy folks, I work on a litte project for a time tracker and use Core Data for storing the values. Every timer Note has a seconds value stored that runs from inside of each timer view. I want to populate now these values to the parent view, but it's not working even when binding the note to the view. I know i have to populate the changes somehow... Can somebody help?
ContentView:
import SwiftUI
extension Int: Identifiable {
public var id: Int { self }
}
struct ContentView: View {
let coreDM: CoreDataManager
@State private var noteTitle: String = ""
@State private var notes: [Note] = [Note]() // That's the Core Data Model
private func populateNotes() {
notes = coreDM.getAllNotes()
}
var body: some View {
VStack {
if notes.count > 0 {
ForEach(0..<$notes.count,id: \.self) { i in
Text("\(notes[i].seconds)")
}
}
TextField("Enter title", text: $noteTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("Save") {
coreDM.saveNote(title: noteTitle, seconds: 0)
populateNotes()
}
List {
if notes.count > 0 {
ForEach(0..<$notes.count,id: \.self) { i in
NoteListView(note: $notes[i], coreDM: coreDM)
Button("Delete"){
coreDM.deleteNote(note: notes[i])
populateNotes()
}
}
}
}.listStyle(PlainListStyle())
Spacer()
}.padding()
.onAppear(perform: {
populateNotes()
})
}
}
NoteListView:
import SwiftUI
import Combine
struct NoteListView: View {
@Binding var note: Note
let coreDM: CoreDataManager
@State private var noteSeconds: Double = 0.0
@State private var noteIsRunning: Bool = false
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
var body: some View {
VStack{
Text(note.title ?? "")
Text("\(noteSeconds)")
.onReceive(timer) { time in
if noteIsRunning {
noteSeconds += 1
note.seconds = noteSeconds
}
}
if noteIsRunning {
Image(systemName: "pause.circle")
.resizable()
.frame(width:20, height: 20)
.onTapGesture {
withAnimation{
noteIsRunning.toggle()
note.seconds = noteSeconds
coreDM.updateNote()
}
}
}else{
Image(systemName: "record.circle")
.resizable()
.foregroundColor(.orange)
.frame(width:20, height: 20)
.onTapGesture {
withAnimation{
noteIsRunning.toggle()
}
}
}
}
.onAppear(){
noteSeconds = note.seconds
}
}
}
CoreDataManager:
import Foundation
import CoreData
class CoreDataManager {
let persistentContainer: NSPersistentContainer
init() {
persistentContainer = NSPersistentContainer(name: "TimeTrackerDataModel2")
persistentContainer.loadPersistentStores { (description, error) in
if let error = error {
fatalError("Core Data Store failed \(error.localizedDescription)")
}
}
}
func updateNote() {
do {
try persistentContainer.viewContext.save()
} catch {
persistentContainer.viewContext.rollback()
}
}
func deleteNote(note: Note) {
persistentContainer.viewContext.delete(note)
do {
try persistentContainer.viewContext.save()
} catch {
persistentContainer.viewContext.rollback()
print("Failed to save context \(error)")
}
}
func getAllNotes() -> [Note] {
let fetchRequest: NSFetchRequest<Note> = Note.fetchRequest()
do {
return try persistentContainer.viewContext.fetch(fetchRequest)
} catch {
return []
}
}
func saveNote(title: String, seconds: Double) {
let note = Note(context: persistentContainer.viewContext)
note.title = title
note.seconds = seconds
do {
try persistentContainer.viewContext.save()
} catch {
print("Failed to save note: \(error)")
}
}
}