NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: Accessing dictionary values stored in an array linked to class in another view

Forums > SwiftUI

I have a picker that you select a manufacturer from, the a second picker which will list the models of said manufacturer.

The dimensions of the models are stored as individual dictionaries in a seperate swift file than the View file.

I have an array of the dictionaries in the view file, I would like to somehow do a mathematical operation with either of the elements of the dictionary based on the model selection in the picker.

import SwiftUI

struct ArrayLengthCalc: View {
    let jinkoLW = [Panels().BifacialHC72M520_540Watt, Panels().BifacialHC72M545Watt, Panels().BifacialHC72M515_535Watt, Panels().TigerPro7RL4_TV565_585Watt, Panels()._72MHC520_540Watt, Panels().TigerPro60HC440_460Watt, Panels().TR60M420_435WattMono_facial, Panels().TR60M440WattMono_facial, Panels().TigerPro54HC395_415Watt, Panels().TR60M430_450Watt_Mono_facial, Panels().TigerPro60HC435_455Watt, Panels().TigerPro78HC575_595Watt, Panels().TigerPro72HC530_550Watt, Panels()._72MHC560Watt]

    var panelMan = Panels().panelMan

    @State private var selectedMan = ""
    @State private var selectedModel = "".replacingOccurrences(of: " ", with: "")
    @State private var midWidth = ""
    @State private var panelAmount = ""

    var body: some View {
        VStack {
            Text("Array Length Calculator")
                .font(.title.weight(.semibold))
            Form {
                Section {
                    List {
                        Picker("Panel Manufacturer", selection: $selectedMan) {
                            ForEach(panelMan, id: \.self) {
                                Text($0)
                            }
                        }
                    }
                }
                Section {
                    List {

                        if selectedMan == "Jinko Solar" {
                            Picker("Panel Model", selection: $selectedModel) {
                                ForEach(Panels().panelModelJinko, id: \.self) {
                                    Text($0)
                                }
                            }
                        }
                        else if selectedMan == "Longi" {
                            Picker("Panel Model", selection: $selectedModel) {
                                ForEach(Panels().panelModelLongi, id: \.self) {
                                    Text($0)
                                }
                            }
                        }
                        else if selectedMan == "REC" {
                            Picker("Panel Model", selection: $selectedModel) {
                                ForEach(Panels().panelModelREC, id: \.self) {
                                    Text($0)
                                }
                            }
                        }
                    }
                }
                Section {
                    TextField("Amount of Panels", text: $panelAmount)
                } header: {
                    Text("Amount of Panels")
                }
                Section {
                    TextField("Mid Clamp Width", text: $midWidth)
                } header: {
                    Text("Mid Clamp Width (mm)")
                }
                Section {
                    Button("Calculate") {
                        let panelAm = Int(panelAmount) ?? 0
                        let midW = Int(midWidth) ?? 0

//                        Math to go here, would like to do "panelAm * Panels().selectedmodel" essentially.

                    }
                }
                Section {
                    Text("")
                } header: {
                    Text("Panel to Panel (mm)")
                }
            }
        }
    }
}

struct ArrayLengthCalc_Previews: PreviewProvider {
    static var previews: some View {
        ArrayLengthCalc()
    }
}

The swift file with the data is as below:

import Foundation

class Panels: ObservableObject {

    @Published var panelMan: [String] = ["None", "Jinko Solar", "Longi", "REC", "Sunpower", "Hyundai", "Risen"]

    @Published var panelModelJinko: [String] = ["None", "Bifacial HC 72M 520-540 Watt", "Bifacial HC 72M 545Watt", "Bifacial HC 72M 515-535 Watt", "Tiger Pro 7RL4-TV 565-585 Watt", "_72M HC 520-540 Watt", "Tiger Pro 60HC 440-460 Watt", "TR 60M 420-435 Watt Mono-facial", "TR 60M 440 Watt Mono-facial", "Tiger Pro 54HC 395-415 Watt", "TR 60M 430-450 Watt Mono-facial", "Tiger Pro 60HC 435-455 Watt", "Tiger Pro 78HC 575-595 Watt", "Tiger Pro 72HC 530-550 Watt", "_72M HC 560 Watt"]

    @Published var panelModelLongi: [String] = []
    @Published var panelModelREC: [String] = ["None", "TwinPeak 4", "N-Peak 2", "Alpha Pure", "Alpha Pure-R"]

    @Published var BifacialHC72M520_540Watt: Dictionary = ["Length": 2274, "Width": 1134]
    @Published var BifacialHC72M545Watt: Dictionary = ["Length": 2274, "Width": 1134]
    @Published var BifacialHC72M515_535Watt: Dictionary = ["Length": 2274, "Width": 1134]
    @Published var TigerPro7RL4_TV565_585Watt: Dictionary = ["Length":2411 ,"Width": 1134]
    @Published var _72MHC520_540Watt: Dictionary = ["Length": 2274, "Width": 1134]
    @Published var TigerPro60HC440_460Watt: Dictionary = ["Length": 1903, "Width": 1134]
    @Published var TR60M420_435WattMono_facial: Dictionary = ["Length": 1868, "Width": 1134]
    @Published var TR60M440WattMono_facial: Dictionary = ["Length": 1868, "Width": 1134]
    @Published var TigerPro54HC395_415Watt: Dictionary = ["Length": 1718, "Width": 1134]
    @Published var TR60M430_450Watt_Mono_facial:Dictionary = ["Length": 1868, "Width": 1134]
    @Published var TigerPro60HC435_455Watt: Dictionary = ["Length": 1903, "Width": 1134]
    @Published var TigerPro78HC575_595Watt: Dictionary = ["Length": 2465, "Width": 1134]
    @Published var TigerPro72HC530_550Watt: Dictionary = ["Length": 2274, "Width": 1134]
    @Published var _72MHC560Watt: Dictionary = ["Length": 2274, "Width": 1134]

   

Honestly, I would start by rethinking your data model. The way you have it right now is a bit difficult to make sense of. The variable names don't really give the person reading your code much of a clue to what they will be recieving from them. Also, there is no need to have all of those published variables. From what I can tell, all of the data in your ObservedObject class is data that you would want to be constant and never manipulated by the user. So, there is no reason for them to be published, or to be variables at all.

I came up with a different way of creating the data model, and honestly, I don't think it's all that great still. But, I came up with it rather quickly and didn't want to spend all day on it.

Anyway, it accomplishes what you are wanting to do, and maybe it will give you some hints as to how you might accomplish your goal in an even better way.

This is the new data model that I came up with. Instead of having so many published variables, it uses static let arrays of Panel [Panel] to store the different models for each manufacturer, so that they will not accidentally be changed. Then, it has an enum that will return the proper array of panel options depending on the manufacturer that is selected. Notice, that now the model's name, height, and width, are all stored in a Panel struct instance, so that you have access to all the data for a panel in one place.

I didn't fill in all of the info for all of the panel types, so you would have to do that part on your own.

struct Panels {
    enum Manufacturer: String, CaseIterable, Identifiable {
        case none = "None"
        case jinkoSolar = "Jinko Solar"
        case longi = "Longi"
        case rec = "REC"
        case sunpower = "Sunpower"
        case hyundai = "Hyundai"
        case risen = "Risen"

        var id: RawValue {
            self.rawValue
        }

        var availablePanelModels: [Panel] {
            switch(self) {
            case .none:
                return []
            case .jinkoSolar:
                return jinkoPanelModels
            case .longi:
                return longiPanelModels
            case .rec:
                return recPanelModels
            case .sunpower:
                return sunpowerPanelModels
            case .hyundai:
                return hyundaiPanelModels
            case .risen:
                return risenPanelModels
            }
        }
    }

    struct Panel: Hashable, Identifiable {
        var id = UUID()
        let model: String
        let width: Int
        let height: Int
    }

    static let jinkoPanelModels = [
        Panel(model: "None", width: 0, height: 0),
        Panel(model: "Bifacial HC 72M 520-540 Watt", width: 2274, height: 1134),
        Panel(model: "Bifacial HC 72M 545Watt", width: 2274, height: 1134),
        //more panel models here
    ]

    static let longiPanelModels = [
        Panel(model: "None", width: 0, height: 0)
        //more panel models here
    ]

    static let recPanelModels = [
        Panel(model: "None", width: 0, height: 0)
        //more panel models here
    ]

    static let sunpowerPanelModels = [
        Panel(model: "None", width: 0, height: 0)
        //more panel models here
    ]

    static let hyundaiPanelModels = [
        Panel(model: "None", width: 0, height: 0)
        //more panel models here
    ]

    static let risenPanelModels = [
        Panel(model: "None", width: 0, height: 0)
        //more panel models here
    ]
}

I had to make some changes to your View to make it fit with the new data model. But, it is mostly the same as what you had. I also removed some Lists that were just unnecessary to have in there.

struct ArrayLengthCalc: View {

    @State private var panelManufacturer = Panels.Manufacturer.none
    @State private var selectedModel =  Panels.Panel(model: "None", width: 0, height: 0)
    @State private var midWidth = ""
    @State private var panelAmount = ""
    @State private var calculationResult = 0

    var body: some View {
        VStack {
            Text("Array Length Calculator")
                .font(.title.weight(.semibold))

            Form {
                Section {
                    Picker("Panel Manufacturer", selection: $panelManufacturer) {
                        ForEach(Panels.Manufacturer.allCases) {
                            Text($0.rawValue).tag($0 as Panels.Manufacturer)
                        }
                    }
                }

                Section {
                    Picker("Panel Model", selection: $selectedModel) {
                        ForEach(panelManufacturer.availablePanelModels) { panel in
                            Text(panel.model).tag(panel)
                        }
                    }
                }

                Section {
                    TextField("Amount of Panels", text: $panelAmount)
                } header: {
                    Text("Amount of Panels")
                }

                Section {
                    TextField("Mid Clamp Width", text: $midWidth)
                } header: {
                    Text("Mid Clamp Width (mm)")
                }

                Section {
                    Button("Calculate") {
                        calculate()
                    }
                }

                Section {
                    Text("\(calculationResult)")
                } header: {
                    Text("Panel to Panel (mm)")
                }
            }
        }
    }

    func calculate() {
        let panelAm = Int(panelAmount) ?? 0
        let midW = Int(midWidth) ?? 0

        calculationResult = panelAm * selectedModel.width
    }
}

2      

@FlyOstrich - kudos , this was a herculian effort ...

1      

@FlyOstrich Mate, you are an absolute genius, Can't thank you enough. Please pardon my very basic skills and knowledge.

   

Hacking with Swift is sponsored by Play

SPONSORED Play is the first native iOS design tool created for designers and engineers. You can install Play for iOS and iPad today and sign up to check out the Beta of our macOS app with SwiftUI code export. We're also hiring engineers!

Click to learn more about Play!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.