I have a core data program. I run my fetch request in a class i.e. a view model and assign it to a StateObject in the ContentView. When I attempt to use the fetch request results from the view model in a selected view, the DataTable, I get this message: Accessing StateObject's object without being installed on a View. This will create a new instance each time. Not sure what to do. Below is my code:
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@State var selection: DataDisplayed? = nil
@StateObject var dataViewModel: FetchCoreData = FetchCoreData()
var body: some View {
NavigationSplitView{
sidebarContent
.navigationSplitViewColumnWidth(min: 200, ideal: 200, max: 200)
} detail: {
detailContent
}
.navigationSplitViewStyle(.balanced)
.navigationTitle("Testing")
.frame(width: 1000, height: 800)
}
}
extension ContentView {
@ViewBuilder
var detailContent: some View {
if let selection = selection {
detailContent(for: selection)
.buttonStyle(.bordered)
} else {
Text("Make A Selection")
}
}
@ViewBuilder
func detailContent(for screen: DataDisplayed) -> some View {
switch screen {
case .VOODT: DataTable(dataModel: dataViewModel.fetchRequest)
case .NWDT: Text("Start")
case .VOOG1: Text("VOO Graph 1 Year")
default: Text("Not yet implemented")
}
}
}
class FetchCoreData: ObservableObject {
@FetchRequest var fetchRequest: FetchedResults<TradingDayPrices>
init() {
_fetchRequest = FetchRequest<TradingDayPrices>(sortDescriptors: [NSSortDescriptor(key: "timeStamp", ascending: true)], predicate: NSPredicate(format: "net > %d", 0.0))
}
}
struct DataTable: View {
var dataModel: FetchedResults<TradingDayPrices>
init(dataModel: FetchedResults<TradingDayPrices>) {
self.dataModel = dataModel
}
var body: some View {. // fails on this line ########################
List(dataModel.fetchRequest, id: \.self) { item in
Text("\(dateToStringFormatter.string(from: item.timeStamp!)) - ") +
Text("\(item.vooClose) ")
}
}
}
Thank you MobileTen. I needed to use async and await. Below are the main call, view model and data table structure that work.
@main
struct NavigationStackApp: App {
let coreDataManager = CoreDataManager()
var body: some Scene {
WindowGroup {
ContentView(fetchedCoreData: FetchCoreData(persistentContainer: coreDataManager.persistentContainer))
}
}
}
class FetchCoreData: ObservableObject {
@Published var closingValues: [TradingDayPrices] = []
private (set) var persistentContainer: NSPersistentContainer
init(persistentContainer: NSPersistentContainer) {
self.persistentContainer = persistentContainer
Task {
closingValues = await FetchResults(moc: persistentContainer.viewContext)
}
}
}
func FetchResults(moc: NSManagedObjectContext) async -> [TradingDayPrices] {
var coreDataValues: [TradingDayPrices] = []
let fetchRequest : NSFetchRequest<TradingDayPrices> = TradingDayPrices.fetchRequest()
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "timeStamp", ascending: true)]
fetchRequest.predicate = NSPredicate(format: "netWorth > %d", 0.0)
do {
coreDataValues = try moc.fetch(fetchRequest)
} catch let error {
print("Error fetching max date. \(error.localizedDescription)")
}
return coreDataValues
}
struct DataTable: View {
var closingValues: [TradingDayPrices] = []
init(closingValues: [TradingDayPrices]) {
self.closingValues = closingValues
}
var body: some View {
List(closingValues, id: \.self) { item in
Text("\(dateToStringFormatter.string(from: item.timeStamp!)) - ") +
Text("\(item.vooClose) ")
}
}
}