Issue
This Content is from Stack Overflow. Question asked by dano9258
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()
}
} // end list
} //end if
} // end Vstack
.onAppear {
coreDataViewModel.fetchRecords()
}
} // end body view
} // end LogView view
struct SleepRow: View {
@StateObject var coreDataViewModel = CoreDataViewModel()
var body: some View {
ForEach(coreDataViewModel.savedRecords, id: .id) { record in
HStack {
VStack(alignment: .leading) {
Text("Sleep Results").bold()
.font(.system(size:14))
// Display Hours Slept
Text("(record.hoursSlept, specifier: "%.2f") Hours Slept")
.font(.system(size:11)).foregroundColor(.red)
// Display AHI
Text("(record.ahiReading, specifier: "%.2f") AHI")
.font(.system(size:11)).foregroundColor(.gray)
......AND IT KEEPS GOING WITH MORE VALUES BUT DON'T WANT TO BORE YOU
Solution
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
This Question was asked in StackOverflow by dano9258 and Answered by workingdog support Ukraine It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.