This is what I have in code:
struct ServicesView: View {
@FetchRequest(entity: Category.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Category.name, ascending: false)], animation: .easeIn) var results: FetchedResults<Category>
var body: some View {
List(results) { category in
VStack(alignment: .leading, spacing: 3, content: {
Text(category.name)
.font(.system(size: 12))
.foregroundColor(.white)
Text("x\(category.services.count)")
})
}
.overlay(
Text(results.isEmpty ? "Nothing here" : "")
)
.onAppear {
print("😋")
print(Category.numberOfEntities())
}
}
}
On console is displayed:
😋
10
Why there is nothing on the list?
How number is calculated?
extension NSManagedObjectContext {
static func defaultContext() -> NSManagedObjectContext {
CoreDataManager.shared.defaultContext!
}
}
protocol Fetchable {
associatedtype FetchableType: NSManagedObject = Self
static func numberOfEntities() -> Int
}
extension Fetchable where Self: NSManagedObject {
static var entityName: String {
entity().name ?? ""
}
static func numberOfEntities() -> Int {
let request = NSFetchRequest<FetchableType>(entityName: entityName)
let context = NSManagedObjectContext.defaultContext()
do {
return try context.count(for: request)
} catch let error as NSError {
print("❌ Core Data Count Error \(error), \(error.userInfo)")
return 0
}
}
}
I suppose the issue is here, because I don't assign @Environment’s managedObjectContext
anywhere. How should I do it?
@main
struct Watch_AppApp: App {
var body: some Scene {
WindowGroup {
TabView {
TimerView()
ContentView()
ServicesView() // how do I assign here managed object context?
Text("4th page")
}
.tabViewStyle(PageTabViewStyle())
.onAppear(perform: loadData) //load data, fetch categories from cloudkit and save to core data, is is fetched and saved
}
}
}
First of all you have to add the ManagedObjectContext
to your view from which you are trying to fetch the data from.
You can add it like this to your view:
struct ServicesView: View {
// The context for your view
@Environment(\.managedObjectContext) var viewContext
@FetchRequest(entity: Category.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \Category.name, ascending: false)], animation: .easeIn) var results: FetchedResults<Category>
var body: some View {
List(results) { category in
VStack(alignment: .leading, spacing: 3, content: {
Text(category.name)
.font(.system(size: 12))
.foregroundColor(.white)
Text("x\(category.services.count)")
})
}
.overlay(
Text(results.isEmpty ? "Nothing here" : "")
)
.onAppear {
print("😋")
print(Category.numberOfEntities())
}
}
}
To pass the context from your entry view you have to get the context from your PersistenceController
, like so:
@main
struct Watch_AppApp: App {
var body: some Scene {
WindowGroup {
TabView {
TimerView()
ContentView()
ServicesView()
// Assign the context
.environment(\.managedObjectContext, PersistenceController.shared.container.context)
Text("4th page")
}
.tabViewStyle(PageTabViewStyle())
.onAppear(perform: loadData) //load data, fetch categories from cloudkit and save to core data, is is fetched and saved
}
}
}
You can find the documentation of Core Data here: https://developer.apple.com/documentation/coredata