Swift - access attribute in array of core data entities in a table column via a variable

The below code works. I pass in an array of core data entities and display attributes in a table. In the second table column I use a switch case statement to handle the 3 possible attributes I want to display. I could eliminate the switch case if I could figure out how to access a given core data attribute via a variable that contains the specific attribute name but have been unable to determine how to do so. Two attempts are commented out in the code.

struct DataTable: View {
    private var closingValues: Array<TradingDayPrices>
    var heading: String
    var attribute: String
    init(closingValues: [TradingDayPrices], heading: String, attribute: String) {
        self.closingValues = closingValues
        self.heading = heading
        self.attribute = attribute
    }
    var body: some View {
        Text(heading)
            .foregroundColor(.black)
            .font(Font.custom("Arial", size: 18))
            .bold()
            .padding(.top, 10)
        Table(self.closingValues) {
            TableColumn("Date") { value in
                HStack {
                    Spacer()
                    Text(dateToStringFormatter.string(from: value.timeStamp!))
                    Spacer()
                }
            }
            .width(100)
            TableColumn("Closing Value") { value in
                HStack {
                    Spacer()
//                    Text(String(format: "$ %.2f", value(forKey: attribute)))
//                    Text(String(format: "$ %.2f", value(attribute)))
                    switch attribute {
                    case "s1Close":
                        Text(String(format: "$ %.2f", value.s1Close))
                    case "s2Close":
                        Text(String(format: "$ %.2f", value.s2Close))
                    default:
                        Text(String(format: "$ %.2f", value.s3Close))
                    }
                    Spacer()
                }
            }
            .width(100)
        }
        .foregroundColor(.black)
        .font(Font.custom("Arial", size: 16))
        .frame(width: 250)
        Spacer()
            .frame(height: 30)
    }
}
Answered by ChrisMH in 752171022

I went about solving the problem a little differently. After fetching the core data into an array, I use the map functionality to generate arrays based the structure below, all in the view model. I can then make the Data Table structure generic, i.e. work with any array of objects based on the structure. Works.

struct ClosingValue: Identifiable {
    var timeStamp: Date
    var close: Double
    var id = UUID()
}

// partial code in my view model.  tempValues is array of objects based on structure above.

   tempValues = closingValues.map {
            tempEntity = ClosingValue(timeStamp: $0.timeStamp!, close: $0.s1Close)
        }
        return tempEntity
    }

// Data Table structure
struct DataTable: View {
    
    var closingValues: Array<ClosingValue>
    var heading: String
    
    init(closingValues: Array<ClosingValue> , heading: String) {
        self.closingValues = closingValues
        self.heading = heading
    }
    var body: some View {
        Text(heading)
            .foregroundColor(.black)
            .font(Font.custom("Arial", size: 18))
            .bold()
            .padding(.top, 10)
        Table (closingValues) {
            TableColumn("Date") { value in
                HStack {
                    Spacer()
                    Text(dateToStringFormatter.string(from: value.timeStamp))
                    Spacer()
                }
            }
            .width(100)
            TableColumn("ClosingValue") { value in
                HStack {
                    Spacer()
                    Text(String(format: "$ %.2f", value.close))
                    Spacer()
                }
            }
            .width(100)
        }
        .foregroundColor(.black)
        .font(Font.custom("Arial", size: 16))
        .frame(width: 250)
        Spacer()
            .frame(height: 30)
    }
}

Accepted Answer

I went about solving the problem a little differently. After fetching the core data into an array, I use the map functionality to generate arrays based the structure below, all in the view model. I can then make the Data Table structure generic, i.e. work with any array of objects based on the structure. Works.

struct ClosingValue: Identifiable {
    var timeStamp: Date
    var close: Double
    var id = UUID()
}

// partial code in my view model.  tempValues is array of objects based on structure above.

   tempValues = closingValues.map {
            tempEntity = ClosingValue(timeStamp: $0.timeStamp!, close: $0.s1Close)
        }
        return tempEntity
    }

// Data Table structure
struct DataTable: View {
    
    var closingValues: Array<ClosingValue>
    var heading: String
    
    init(closingValues: Array<ClosingValue> , heading: String) {
        self.closingValues = closingValues
        self.heading = heading
    }
    var body: some View {
        Text(heading)
            .foregroundColor(.black)
            .font(Font.custom("Arial", size: 18))
            .bold()
            .padding(.top, 10)
        Table (closingValues) {
            TableColumn("Date") { value in
                HStack {
                    Spacer()
                    Text(dateToStringFormatter.string(from: value.timeStamp))
                    Spacer()
                }
            }
            .width(100)
            TableColumn("ClosingValue") { value in
                HStack {
                    Spacer()
                    Text(String(format: "$ %.2f", value.close))
                    Spacer()
                }
            }
            .width(100)
        }
        .foregroundColor(.black)
        .font(Font.custom("Arial", size: 16))
        .frame(width: 250)
        Spacer()
            .frame(height: 30)
    }
}

Swift - access attribute in array of core data entities in a table column via a variable
 
 
Q