Why is this showing only the first input values for each record?

Viewed 86

**Edit: I’m trying to figure out how to pass the SleepModel record from core data from my log view to my sleep row view. Once that is done, I need to figure out why it’s only displaying the 1st inputs everytime.

I have a CoreData setup where it saves the SleepModel correctly with unique ID, and values. I've checked and the count of SleepModel records goes up with each button click so Im pretty sure CoreData is setup and its saving correctly. However, while it does add another list row to display data, it is only displaying the very first input (not whatever input you put for subsequent entries). Here is what I have for the log view and sleep row views:

struct LogView: View {
    
    @StateObject var coreDataViewModel = CoreDataViewModel()
    
    var body: some View {
        VStack {
            if !coreDataViewModel.savedRecords.isEmpty {
                List {
                    ForEach(coreDataViewModel.savedRecords, id: \.id) { record in
                        SleepRow(sleep:record)
                    }
                } // end list
            } //end if
        }   // end Vstack
        .onAppear {
                coreDataViewModel.fetchRecords()
            }
    }  // end body view
} // end LogView view
struct SleepRow: View {
    
    @StateObject var coreDataViewModel = CoreDataViewModel()
    Var sleep:SleepModel
    
    var body: some View {
            HStack {
                
                    VStack(alignment: .leading) {
                        Text("Sleep Results").bold()
                            .font(.system(size:14))
        // Display Hours Slept
                 
                            Text("\(sleep.hoursSlept, specifier: "%.2f") Hours Slept")
                                .font(.system(size:11)).foregroundColor(.red)
                        
 
1 Answers

try this example code, where you have one source of truth, @StateObject var coreDataViewModel = CoreDataViewModel() in LogView, and pass the model around to SleepRow using .environmentObject(coreDataViewModel). Note you do not use coreDataViewModel in SleepRow, so you could just, not pass the model to it.

// for testing
struct SleepModel: Identifiable, Hashable {
        let id = UUID().uuidString // ID variable
        var hoursSlept: Double // Hours slept variable
}

// for testing
class CoreDataViewModel: ObservableObject {
    @Published var savedRecords: [SleepModel] = []
    
    func fetchRecords() {
        savedRecords = [SleepModel(hoursSlept: 1.1),
                        SleepModel(hoursSlept: 2.2),
                        SleepModel(hoursSlept: 3.3),
                        SleepModel(hoursSlept: 4.4)
        ]
    }
}

struct SleepRow: View {
    @EnvironmentObject var coreDataViewModel: CoreDataViewModel // <-- here, only if required
    @State var sleep: SleepModel // <-- here
    
    var body: some View {
        HStack {
            VStack(alignment: .leading) {
                Text("Sleep Results").bold()
                    .font(.system(size:14))
                Text("\(sleep.hoursSlept, specifier: "%.2f") Hours Slept")
                    .font(.system(size:11)).foregroundColor(.red)
            }
        }
    }
}

struct LogView: View {
    @StateObject var coreDataViewModel = CoreDataViewModel()
    
    var body: some View {
        VStack {
                List {
                    ForEach(coreDataViewModel.savedRecords, id: \.id) { record in
                        SleepRow(sleep: record)
                    }
                } // end list
        }   // end Vstack
        .environmentObject(coreDataViewModel) // <-- here, only if required in SleepRow
        .onAppear {
                coreDataViewModel.fetchRecords()
            }
    }  // end body view
} // end LogView view
Related