user2632918
user2632918

Reputation:

Using the data of a picker for fetching values would not work

I try now since a while to use data from a entity that be selected in a picker. But I feel in the moment like running again a wall and don't see the next step. So I hope I can get a tip from you which push me into the better way.

I have the following two entities, who be related with one-to-many (one manufacturer can have multiple type of devices)

enter image description here

enter image description here

In the application I list all types in a picker that it can be choosen for the calculation.

enter image description here

The code for the picker is

Picker("Select Type", selection: $selectedType) {
                    ForEach(0..<types.count, id: \.self) { index in
                        Text("\(types[index].wrappedName)")
                            .tag(index)
                    }
                }

I can't get the origin indexkey for the row that I select in the picker. Is this the uuid? Also I can't add the manufacturer.name to the text in the picker.

Please give me a tip in which way I have to look.

Thanks a lot.

Here is the fully View

import SwiftUI
import CoreData

struct CalculateCopyView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        sortDescriptors: [],
        predicate: NSPredicate(format: "favorite == %@", true as NSNumber),
        animation: .default)
    var types: FetchedResults<TypeEntity>
    
    @State private var selectedType: Int  = 0
    
    @State private var selectedBarString = "Top"
    let barOptions: [String] = ["Top","Front"]
    
    //This Data should be filled from database
    @State private var winkel: Double = 15
    @State private var laengeSchleifstueck: Double = 140
    @State private var durchmesserSchleifrad: Double = 250.3
    @State private var horizontal: Double = 50
    @State private var vertikal: Double = 29
    //***********************
    
    let formatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter
    }()

    func calculateBar(h: Double,v: Double) -> Double {
        let t = h + v
        
        return t
    }
    
    //This function should called always when one of the pickers would be
    //changed and when the view would viewed for the first time with the 
    //first automatically selected value from the type-picker
    
    func fetchDataforSelectedType (v: String) {
        // v = value of the picker for the types (devices)
        @FetchRequest(
            sortDescriptors: [],
            predicate: NSPredicate(format: "name == %@", v),
            animation: .default
        )
        var types: FetchedResults<TypeEntity>
        switch selectedBarString {
            case "top":
                horizontal = types[0].topHorizontal
                vertikal = types[0].topVertical
            case "front":
                horizontal = types[0].frontHorizontal
                vertikal = types[0].frontVertical
            default:
                print("no kind of bar is choosen")
        }
    }
    
    var body: some View {
        Form {
            Section {
                VStack {
                    Picker("Select Type", selection: $selectedType) {
                        ForEach(0..<types.count, id: \.self) { type in
                            Text("\(types[type].wrappedName)")
                                .tag(types[type])
                        }
                    }
                }
            }
                
            Section {
                VStack {
                    Picker(selection: $selectedBarString, label: Text("Select Bar")) {
                        ForEach(barOptions.indices, id: \.self) { index in
                            Text(barOptions[index])
                                .tag(barOptions[index])
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
            }
            
            Section {
                VStack {
                    HStack {
                        Text("Schleifrad")
                        TextField("Enter your score", value: $durchmesserSchleifrad, formatter: formatter)
                            .textFieldStyle(OutlinedTextFieldStyle(icon: Image(systemName: "pencil")))
                    }
                }
                .onTapGesture {
                    hideKeyboard()
                }
                
                VStack {
                    HStack {
                        Text("length tool")
                        TextField("Enter your score", value: $laengeSchleifstueck, formatter: formatter)
                            .textFieldStyle(OutlinedTextFieldStyle(icon: Image(systemName: "pencil")))
                    }
                }
                .onTapGesture {
                    hideKeyboard()
                }
                
                VStack {
                    Text("angle")
                        .frame(maxWidth: .infinity, alignment: .leading)
                    HStack {
                        Slider(value: $winkel , in: 7.0...32.0, step: 1.0)
                        Text(
                            String(format: "%.0f °", winkel)
                        )
                    }
                }
                .onTapGesture {
                    hideKeyboard()
                }
            }
            .padding()
            
            Section {
                VStack {
                    HStack {
                        Text("Topbar: " )
                            .font(.title)
                        Text(String(format: "%.1f mm", calculateBar(h: horizontal, v: vertikal)))
                            .font(.title)
                            .frame(maxWidth: .infinity, alignment: .trailing)
                    }
                }
                .onTapGesture {
                    hideKeyboard()
                }
            }
        }
    }
}

Upvotes: 0

Views: 44

Answers (2)

ChrisR
ChrisR

Reputation: 12125

Alternatively you could let the Picker pick a 'Type' directly. Just define selectedType as type TypeEntity?.

The manufacturer can be accessed directly from the type through the to-one relation: type.manufacturer

struct TypesView: View {
    
    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \TypeEntity.name, ascending: true)],
        animation: .default)
    private var types: FetchedResults<TypeEntity>

    @State private var selectedType: TypeEntity? = nil  // directly pick an (optional) TypeEntity
    
    var body: some View {
        
        Form {
            Picker("Select Type", selection: $selectedType) {
                Text("keine Auswahl").tag(nil as TypeEntity?)
                ForEach(types) { type in
                    Text(type.name ?? "?").tag(type as TypeEntity?)
                }
            }
            
            if let type = selectedType {
                let hersteller = type.manufacturer // access manufacturer through type to-one relation
                Text("Hersteller: \(hersteller?.name ?? "?")")
            }
        }
        .padding()
    }
}

Upvotes: 1

vadian
vadian

Reputation: 285064

As selectedType is Int, the tag must be Int, too.

Renaming type as index makes it clearer

Picker("Select Type", selection: $selectedType) {
    ForEach(0..<types.count, id: \.self) { index in
        Text(types[index].wrappedName)
            .tag(index)
    }
}

And – unrelated – string interpolating a string is pointless

Upvotes: 1

Related Questions