I created a CoreData Entity called Event
with its attributes category
( String) and isBlack
(Bool). I also created a Button & a VGrid (Xcode 12 beta).
The button, upon clicked, adds and saves some entries to CoreData. I have a @FetchRequest
and a func update
which returns a dictionary that groups the CoreData entries in its respective categories.
Then I let the VGrid do it's magic and display one section per category, using a SFSymbols Image.
What I want to achieve is that the VGrid displays an Image depending how many "true" Booleans are inside each category. So if, for example, the true Booleans are in the majority in a category, I want to display circle.filled
, otherwise just circle
.
Here's the code, since it makes use of Grid, it only works in Xcode 12 (beta):
struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: Event.entity(),sortDescriptors: []) var events: FetchedResults<Event>
// grouping CoreData entries by categories, returning Dictionary:
func update(_ result : FetchedResults<Event>)-> [[Event]]{
return Dictionary(grouping: result){ (element : Event) in
element.category!
}.values.map{$0}
}
let columns = [
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible()),
GridItem(.flexible())
]
var body: some View {
VStack {
Button(action: {
// adding some events in 5 categories, in total 5 grid colums.
let newEvent1 = Event(context: self.moc)
newEvent1.category = "A"
newEvent1.isBlack = true
let newEvent2 = Event(context: self.moc)
newEvent2.category = "A"
newEvent2.isBlack = true
let newEvent3 = Event(context: self.moc)
newEvent3.category = "A"
newEvent3.isBlack = false
let newEvent4 = Event(context: self.moc)
newEvent4.category = "B"
newEvent4.isBlack = false
let newEvent5 = Event(context: self.moc)
newEvent5.category = "C"
newEvent5.isBlack = true
let newEvent6 = Event(context: self.moc)
newEvent6.category = "C"
newEvent6.isBlack = false
let newEvent7 = Event(context: self.moc)
newEvent7.category = "D"
newEvent7.isBlack = true
let newEvent8 = Event(context: self.moc)
newEvent8.category = "D"
newEvent8.isBlack = true
let newEvent9 = Event(context: self.moc)
newEvent9.category = "D"
newEvent9.isBlack = false
let newEvent10 = Event(context: self.moc)
newEvent10.category = "E"
newEvent10.isBlack = true
try? self.moc.save()
}) {
Text("Add some Events")
}
// Grid:
LazyVGrid(columns: columns, spacing: 40) {
ForEach(update(events), id: \.self) { (section: [Event]) in
NavigationLink(destination: Text("this just a test"))
{
// here comes the part i need advice...
// how would i sum up all the true booleans and check if they're the majority in each category?
if section[0].isBlack == true {
Image(systemName: "circle.fill")
} else {
Image(systemName: "circle")
}
// so what i want to achieve is following images being displayed:
// first column (catergory A): circle.filled (cause true booleans are more)
// second column(catergory B): circle
// third column(catergory C): circle.filled (if equal => same as if true)
// fourth column(catergory D): circle
// fifth Column(catergory E): circle.filled
}
}
}
}
}
}
Any help is greatly appreciated, many thanks.
so today, i figured out how to make it work, although i had to change the isBlack?
Boolean to a String and then reduce the grouped section like this:
let whiteCount = section.reduce(0) { $0 + (($1 as AnyObject).isBlack!.contains("false") ? 1 : 0) }
let blackCount = section.reduce(0) { $0 + (($1 as AnyObject).isBlack!.contains("true") ? 1 : 0) }
Now it's just a matter of comparing the values of whiteCount
and blackCount
and display the respective image in the grid.
I‘d still prefer a solution with booleans instead though.