SwiftUI и CoreData: как подсчитать количество "истинных" логических значений и отобразить результат в VGrid

Я создал объект CoreData под названием Event со своими атрибутами category (Строка) и isBlack(Булево). Я также создал кнопку и VGrid (бета-версия Xcode 12).

При нажатии кнопки добавляются и сохраняются некоторые записи в CoreData. у меня есть@FetchRequest и функция updateкоторый возвращает словарь, который группирует записи CoreData по соответствующим категориям. Затем я позволяю VGrid творить чудеса и отображать по одному разделу для каждой категории, используя изображение SFSymbols.

Я хочу добиться того, чтобы VGrid отображал изображение в зависимости от того, сколько "истинных" логических значений находится внутри каждой категории. Итак, если, например, истинные логические значения находятся в большинстве в категории, я хочу отобразитьcircle.filled, иначе просто circle.

Вот код, поскольку он использует сетку, он работает только в Xcode 12 (бета):

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
                        
                    }
                }
            }
            
        }
    }
}

Любая помощь приветствуется, большое спасибо.

1 ответ

Итак, сегодня я понял, как заставить его работать, хотя мне пришлось изменить isBlack? Boolean в String, а затем уменьшите сгруппированный раздел следующим образом:

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) }

Теперь осталось просто сравнить значения whiteCount а также blackCount и отобразить соответствующее изображение в сетке.

Я все же предпочел бы решение с логическими значениями.

Другие вопросы по тегам