将 Picker 与核心数据一起使用

Posted

技术标签:

【中文标题】将 Picker 与核心数据一起使用【英文标题】:Using Picker with Core Data 【发布时间】:2020-09-23 01:50:27 【问题描述】:

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

我有 2 个 CoreData 实体: 费用

expenseAccount:String 费用类别:字符串 expenseCost:双倍 expenseDate:日期 expenseId:UUID expenseIsMonthly:Bool 费用名称:字符串 类别 类别名称:字符串
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")
                    .onAppearself.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()
    
    
    

【问题讨论】:

【参考方案1】:

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

它是CoreData的默认类型,但是你可以去掉模型内部的Optional值:

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

【讨论】:

非常感谢!!这解决了它。我最终将类别变量更改为字符串?因为我确实希望它是可选的。

以上是关于将 Picker 与核心数据一起使用的主要内容,如果未能解决你的问题,请参考以下文章

如何将 undoManager 与核心数据实体一起使用

如何将 NSOutlineView 与多个核心数据实体作为组一起使用

将 Mantle 与核心数据一起使用 - NSSet 和 NSArray

与核心数据一起使用时预览崩溃

可以将“self”与 NSSortDescriptor 一起使用来按对象本身而不是对象的属性进行排序? (核心数据/NSFetchedResultsController)

SwiftUI Picker 多个错误,核心数据,布局