首页 > 解决方案 > 通过关系列出 CoreData 对象

问题描述

我在没有 CoreData 关系(多次获取)的情况下工作,但我想到我可能应该在这些实体之间实现关系,这样我就可以从单个实体中获取所有属性。

当我直接从 Accounts 实体中为我的 AccountsList.swift 获取 accountNames(以创建帐户)时,它工作得很好,但是当我尝试通过关系(originAccounts)调用它们时,它不会在列表中显示任何内容。类别选择器的相同问题。

我有 3 个 CoreData 实体和两个 Picker(用于类别和帐户)

花费

类别

账户

费用与帐户和类别具有多对一的关系

import SwiftUI
import CoreData

struct ExpenseDetail: View {
    
    
    @Environment(\.managedObjectContext) var context
    @Environment(\.presentationMode) var presentationMode
    
    @FetchRequest(fetchRequest: Expenses.expensesList)
    var results: FetchedResults<Expenses>
    
    
    
    var logToEdit: Expenses?
    
    @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
    }()
    
    
    
    
    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(results) { (log: Expenses) in
                            Text(log.originCategories?.categoryName ?? "No Category").tag(log.originCategories?.categoryName)
                        }
                    }
                    
                    Picker(selection: $account, label: Text("Account")) {
                        ForEach(results) { (log: Expenses) in
                            Text(log.originAccounts?.accountName ?? "No Account").tag(log.originAccounts?.accountName)
                        }
                    }
                    
                    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.originCategories?.categoryName = self.category
        expenseLog.expenseCost = Double(self.amount) ?? 0
        expenseLog.expenseDate = self.date
        expenseLog.originAccounts?.accountName = self.account
        print("\(self.account ?? "NoAccountValue")")
        expenseLog.expenseIsMonthly = self.isMonthly
        
        do {
            try context.save()
        } catch let error as NSError {
            print(error.localizedDescription)
        }
        
        self.presentationMode.wrappedValue.dismiss()
    }
    
    
}

#if canImport(UIKit)
extension View {
    func hideKeyboard() {
        UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}
#endif

struct ExpenseDetail_Previews: PreviewProvider {
    static var previews: some View {
        ExpenseDetail()
        
    }
    
}

struct CheckboxToggleStyle: ToggleStyle {
    func makeBody(configuration: Configuration) -> some View {
        return HStack {
            configuration.label
            Spacer()
            Image(systemName: configuration.isOn ? "checkmark.square" : "square")
                .resizable()
                .frame(width: 22, height: 22)
                .onTapGesture { configuration.isOn.toggle() }
        }
    }
}

如果需要,费用列表获取详细信息

    static var expensesList: NSFetchRequest<Expenses> {
      let request: NSFetchRequest<Expenses> = Expenses.fetchRequest()
      request.sortDescriptors = [NSSortDescriptor(key: "expenseName", ascending: true)]
      return request
    }

标签: swiftcore-data

解决方案


推荐阅读