首页 > 解决方案 > 将 Picker 与核心数据一起使用

问题描述

我在这里看到了许多关于类似问题的回复,但是下面代码中 $category 的选择器似乎不起作用。当我选择选择器时,我会看到 categoryNames 列表,但是当我选择一个时,它不会填充到 $category 中。

我有 2 个 CoreData 实体:费用

import SwiftUI
import CoreData


struct ExpenseDetail: View {
    
    @FetchRequest(
        entity: Categories.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Categories.categoryName, ascending: true)
        ]
    )
    private var result: FetchedResults<Categories>
    
    var logToEdit: Expenses?
    @Environment(\.managedObjectContext) var context
    @State var name: String = ""
    @State var amount: String = ""
    @State var category: String = ""
    @State var date: Date = Date()
    @State var account: String = ""
    @State var isMonthly: Bool = false
    
    var currencyFormatter: NumberFormatter = {
        let f = NumberFormatter()
        f.numberStyle = .currency
        return f
    }()
    
    @Environment(\.presentationMode) var presentationMode
    
    
    var body: some View {
        NavigationView {
            Form{
                TextField("Expense Name", text: $name)
                Section{
                    HStack{
                        TextField("$\(amount)", text: $amount)
                            .keyboardType(.decimalPad)
                            .textFieldStyle(PlainTextFieldStyle())
                            .disableAutocorrection(true).multilineTextAlignment(.leading)
                        
                        
                        
                        
                    }
                    
                    DatePicker(selection: $date, displayedComponents: .date) {
                        Text("Date")
                    }.onAppear{self.hideKeyboard()}
                    
                    
                    Picker(selection: $category, label: Text("Category")) {
                        ForEach(result) { (log: Categories) in
                            Text(log.categoryName ?? "No Category").tag(log.categoryName)
                        }
                    }
                    
                    Picker(selection: $account, label: Text("Account")) {
                        ForEach(result) { (log: Categories) in
                            self.Print("\(log.categoryName ?? "")")
                            Button(action: {
                                // TODO: Implement Edit
                            }) {
                                Text(log.categoryName!.capitalized).tag(self.category)
                            }
                            
                        }
                    }
                    Toggle(isOn: $isMonthly) {
                        Text("Monthly Expense")
                    }.toggleStyle(CheckboxToggleStyle())
                }
                
                Section{
                    Button(action: {
                        onSaveTapped()
                    }) {
                        HStack {
                            Spacer()
                            Text("Save")
                            Spacer()
                        }
                    }
                    
                    
                }
                Section{
                    Button(action: {
                        self.presentationMode.wrappedValue.dismiss()
                    }) {
                        HStack {
                            Spacer()
                            Text("Cancel").foregroundColor(.red)
                            Spacer()
                        }
                        
                    }
                }
            }.navigationBarTitle("Add Expense")
        }
        
    }
    
    private func onSaveTapped() {
        
        let expenseLog: Expenses
        if let logToEdit = self.logToEdit {
            expenseLog = logToEdit
        } else {
            expenseLog = Expenses(context: self.context)
            expenseLog.expenseId = UUID()
        }
        
        expenseLog.expenseName = self.name
        expenseLog.expenseCategory = self.category
        print("\(expenseLog.expenseName ?? "") category Picker: \(self.category)")
        print("\(expenseLog.expenseName ?? "") ExpenseCategory: \(expenseLog.expenseCategory!)")
        expenseLog.expenseCost = Double(self.amount) ?? 0
        print("\(expenseLog.expenseName ?? "") Amount: \(self.amount)")
        print("\(expenseLog.expenseName ?? "")ExpenseCost: \(expenseLog.expenseCost)")
        expenseLog.expenseDate = self.date
        expenseLog.expenseAccount = self.account
        expenseLog.expenseIsMonthly = self.isMonthly
        
        do {
            try context.save()
        } catch let error as NSError {
            print(error.localizedDescription)
        }
        
        self.presentationMode.wrappedValue.dismiss()
    }
    
    
}

标签: swiftswiftui

解决方案


选择值的类型是String,而 Category.categoryName 是 String?。注意添加的?,这意味着它是一个可选的。

它是 CoreData 的默认类型,但您可以删除模型中的 Optional 值:
核心数据 可选

在进行此更改之前,我会问自己没有名称的类别是否有意义。如果是这样,您可能必须使用另一个标识符进行选择。


推荐阅读