Hi HWS Community,
I am working on an App that presents some animal Cards in the Content View showing an image of the animal (for instance a dog) and I am trying to show the number of dogs currently in the Core Data.
Here is the AnimalCard code:
import SwiftUI
struct AnimalCard: View {
var animal: String
var number: Int
var body: some View {
ZStack(alignment: .topTrailing) {
ZStack {
Image(animal)
.resizable()
.scaledToFit()
.frame(width: 140, height: 140)
.cornerRadius(20)
.shadow(color: .secondary, radius: 5, x: 0, y: 1)
}
if number != 0 {
Text(String(number))
.font(.title2)
.frame(width: 20, height: 20)
.padding(5)
.foregroundColor(.white)
.background(.red)
.cornerRadius(50)
.offset(x: 10, y: -10)
}
}
}
}
Here is the ContentView code, it has 3 AnimalCards (Dog, Cat and Bird), the number is being hard coded.
When you click the Card it takes you to the list of animals available in that category (dog, cat or bird).
I also added a button to load some sample data.
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: []) var animals: FetchedResults<Animals>
var body: some View {
NavigationStack {
VStack {
VStack(spacing: 40) {
Text("Animal Shelter")
.font(.largeTitle.bold())
NavigationLink(destination: {
AnimalListView(animal: "Dog", filter: "dog")
}, label: {
AnimalCard(animal: "Dog", number: 2)
})
NavigationLink(destination: {
AnimalListView(animal: "Cat", filter: "cat")
}, label: {
AnimalCard(animal: "Cat", number: 4)
})
NavigationLink(destination: {
AnimalListView(animal: "Bird", filter: "bird")
}, label: {
AnimalCard(animal: "Bird", number: 1)
})
}
Spacer()
// Loading Sample Data
Button(action: {
let coco = Animals(context: moc)
coco.name = "Coco"
coco.animal = "dog"
coco.age = Int16(11)
let brani = Animals(context: moc)
brani.name = "Brani"
brani.animal = "dog"
brani.age = Int16(7)
let hercules = Animals(context: moc)
hercules.name = "Hercules"
hercules.animal = "dog"
hercules.age = Int16(4)
let garfield = Animals(context: moc)
garfield.name = "Garfield"
garfield.animal = "cat"
garfield.age = Int16(2)
let gina = Animals(context: moc)
gina.name = "Gina"
gina.animal = "cat"
gina.age = Int16(3)
try? moc.save()
}, label: {
Text("Load Data")
})
Spacer()
}
.padding()
}
}
}
Here is the AnimalListView file that will be shown with animal name and age.
import SwiftUI
struct AnimalListView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(sortDescriptors: []) var animals: FetchedResults<Animals>
var animal: String
var filter: String
var body: some View {
VStack {
Text(animal)
.font(.largeTitle)
.padding()
FilteredList(filter: filter)
}
}
}
struct AnimalListView_Previews: PreviewProvider {
static var previews: some View {
AnimalListView(animal: "Dog", filter: "dog")
}
}
Here is the FilteredList file.
As you can see, I did add the fetchRequest.count to be shown in the AnimalListView.
import CoreData
import SwiftUI
struct FilteredList: View {
@FetchRequest var fetchRequest: FetchedResults<Animals>
var body: some View {
Text("Number of Animals: \(fetchRequest.count)")
List {
ForEach(fetchRequest, id: \.self) { animals in
VStack {
Text("\(animals.name ?? "Unknown")")
.font(.title)
.frame(maxWidth: .infinity, alignment: .topLeading)
.lineLimit(1)
Text("Age: \(animals.age)")
.font(.headline)
.foregroundColor(.gray)
.frame(maxWidth: .infinity, alignment: .bottomLeading)
}
}
}
}
init(filter: String) {
_fetchRequest = FetchRequest<Animals>(sortDescriptors: [SortDescriptor(\.name)], predicate: NSPredicate(format: "animal == %@", filter))
}
}
Again, the question is how to take the count from the FilteredList and update the AnimalCard in the ContentView?
Thanks for your help.
Renato.