Home > Software engineering >  SwiftUI Create Picker with possibility to add elements
SwiftUI Create Picker with possibility to add elements

Time:05-16

I'm trying to build a swift app with categories, I created a Picker for my categories but I would like to be able to create a Category inside the Picker itself. But I can't figure how to do it properly, I've tried something sketchy but it's kinda ugly and working as I would like to do.

This is my working picker

import SwiftUI

struct CategoryPicker: View {
    @Binding var selection: TransactionCategory?
    @Binding var userData: UserData
    
    var body: some View {
        Picker("category", selection: $selection) {
            CategoryView(category: nil)
                .tag(nil as TransactionCategory?)
            ForEach(userData.transactionsCategories) { category in
                CategoryView(category: category)
                    .tag(category as TransactionCategory?)
            }
        }
    }
}

And this is what I tried so far but it's rendering pretty bad

struct CustomPickerExperiments: View {
    @Binding var selection: TransactionCategory?
    @Binding var userData: UserData
    @Environment(\.presentationMode) var presentation
    
    @State var color = Color.white
    @State var name = ""
    
    var body: some View {
        List {
            Section(header: Text("new-category")) {
                NavigationLink("add-category", destination: CategoryEditView(userData: $userData))
            }
            Section(header: Text("categories")) {
                CategoryView(category: nil)
                    .tag(nil as TransactionCategory?)
                    .onTapGesture {
                        if(selection != nil) {
                            selection = nil as TransactionCategory?
                            self.presentation.wrappedValue.dismiss()
                        }
                    }
                ForEach(userData.transactionsCategories) { category in
                    CategoryView(category: category)
                        .tag(category as TransactionCategory?)
                        .onTapGesture {
                            if(selection != category) {
                                selection = category as TransactionCategory?
                                self.presentation.wrappedValue.dismiss()
                            }
                        }
                }
            }
        }
    }
}

CodePudding user response:

As commented not sure what you try to achieve.
But as I understand it a Menu might be an easier way to go:

struct ContentView: View {
    
    @State private var categories = [
        Category(name: "Beer"),
        Category(name: "Red Wine"),
        Category(name: "Water"),
        Category(name: "Juice")
    ]
    
    @State private var selection: Category?
    @State private var showingSheet = false
    @State private var newName = "New Category"

    
    var body: some View {
        VStack {
            Menu(selection?.name ?? "no selection") {
                Button("New Category ...") {
                        showingSheet = true
                    }

                ForEach(categories) { category in
                    Button(category.name) { selection = category }
                }
            }
        }
        
        .sheet(isPresented: $showingSheet, onDismiss: {
            if !newName.isEmpty {
                let newCat = Category(name: newName)
                categories.append(newCat)
                selection = newCat
                newName = ""
            }
        }, content: {
            VStack(alignment: .leading) {
                Text("Add Category").font(.headline)
                TextField("New Name", text: $newName)
            }.padding()
        })
    }
    
    
    struct Category: Identifiable, Hashable {
        let id = UUID()
        var name: String
    }

}
  • Related