'Why is ForEach not changing my Foreground color correctly in SwiftUI?

I am trying to make a simple Todo app and I'm trying to implement a feature where if I click on a row, the foreground color will be change. However, I have two problems, first when I toggle the boolean value in for my core data attribute, nothing happens on the front end. The value changes true/false but the foreground color is not changing.

Second, when I instead use a simple @State boolean value, ALL the list row foreground colors change instead of just the row I tapped on.

import SwiftUI
import ChameleonFramework

struct ItemView: View {
    
    @Environment(\.managedObjectContext) private var moc
    @StateObject var category: Category
    @State private var showAddItemView = false
    @State private var text = ""
    @State var testBool = false
    var body: some View {
        NavigationView {
            VStack {
                
                List {
                    ForEach(searchResults) { item in
                        
                        Text(item.unwrappedTitle)
                            .foregroundColor(item.unwrappedDone ? .red : .blue)
//                            .foregroundColor(Color(ContrastColorOf(backgroundColor: UIColor(hexString: category.unwrappedColor), returnFlat: true)))
                            .onTapGesture {
                                print(item.unwrappedTitle)
                                item.done.toggle()
                                print(item.done)
                                try? moc.save()
                            }
                            .listRowBackground(Color(UIColor(hexString: category.unwrappedColor)))
                        //                            .listRowBackground(Color(UIColor(hexString: category.unwrappedColor).darken(byPercentage: 0.5)))
                        //                            .listRowBackground(Color(HexColor(hexString: category.unwrappedColor)))
                        
                    }

So using the Core Data variable item.done.toggle does nothing to change the foreground color when toggled but it does switch between true/false. Alternatively, using the @State var testBool changes ALL the rows instead of just the one tapped.

I want to tap on a row and have it change color on only that row.

I made searchResults equal to category.itemArray for purposes of search and filtering.

    var searchResults: [Item] {
        if text.isEmpty {
            return category.itemArray
        } else {
            return category.itemArray.filter { Item in
                Item.title!.lowercased().contains(text.lowercased())
            }
        }
    }



Solution 1:[1]

So I asked another question using mock data on another post and that helped me solve this. Basically, I just needed to make a subview

struct ExtractedView: View {
    @Environment(\.managedObjectContext) private var moc
    @State var testBool = false
    
    let item: Item
    
    var body: some View {
        Text(item.unwrappedTitle)
            .foregroundColor(testBool ? .red : .green)
            .foregroundColor(Color(ContrastColorOf(backgroundColor: UIColor(hexString: item.unwrappedColor), returnFlat: true)))
            .onTapGesture {
                print(item.unwrappedTitle)
                item.done.toggle()
                print(item.unwrappedDone)
                testBool.toggle()
                try? moc.save()
            }
            .listRowBackground(Color(UIColor(hexString: item.unwrappedColor)))
    }
}

And here is the ExtractedView using ForEach..

import SwiftUI
import ChameleonFramework

struct ItemView: View {
    
    @Environment(\.managedObjectContext) private var moc
    @StateObject var category: Category
    @State private var showAddItemView = false
    @State private var text = ""
//    @State var testBool = false
    var body: some View {
        NavigationView {
            VStack {
                
                List {
                    ForEach(searchResults) { item in
                        
                        ExtractedView(item: item)
                        //                            .listRowBackground(Color(UIColor(hexString: category.unwrappedColor).darken(byPercentage: 0.5)))
                        //                            .listRowBackground(Color(HexColor(hexString: category.unwrappedColor)))
                        
                    }
                    .onDelete(perform: deleteItem)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tomas