SwiftUI - 如何包含第二个过滤器来检索 CoreData

问题描述 投票:0回答:1

我正在使用 SwiftUI 开发 iOS 应用程序。在加载后的 ContentView 中,它会显示 SelectAccountView 供用户选择帐户。当流程返回到ContentView时,我想使用selectedAccount值来过滤CoreData。

下面是内容视图

import SwiftUI
import CoreData

struct ContentView: View
{
    @State private var finalAmount: Float = 0
    @State private var selectedEntry: CFTEntry? // Move selectedEntry to ContentView
    @State private var isPresentingEntryEditView = false
    @State private var isPresentingSettingsView = false
    @State private var isPresentingDeleteView = false
    @State private var isPresentingAccountsView = true
    @State private var selectedAccount: CFTAccounts? // Added selectedAccount
    
    @FetchRequest(entity: CFTEntry.entity(), sortDescriptors: [NSSortDescriptor(keyPath: \CFTEntry.cftDate, ascending: false)])
    var entries: FetchedResults<CFTEntry>
    
    var body: some View
    {
        NavigationView
        {
            VStack 
            {
                HStack
                {
                    Image("Wallet") // Add your desired icon system name
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 40, height: 40)
                        .padding(.leading, 20)
                    
                    Spacer()
                    
                    Text("Cash Flow Tracker")
                        .font(.title)
                        .fontWeight(.bold)
//                        .padding(.top, 1)
                    Spacer()
                }
                HStack
                {
                    if let account = selectedAccount 
                    { // Show selected account name
                        Text("Account: \(account.cftAccount ?? "")")
                            .font(.headline)
//                            .fontWeight(.bold)
//                            .padding(.top, 1)
                    } 
                    else
                    {
                        Text("Please, select an Account") // Display message if no account is selected
                            .foregroundColor(.red)
//                            .padding(.top, 1)
                    }
                }
                HStack(spacing: 50)
                {
                    // Descriptions
                    Button(action: {
                        // Show EntrySettingsView
                        isPresentingSettingsView = true
                    }) {
                        Image(systemName: "info.circle")  //.fill")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 25, height: 25)
                    }
                    // Add New Entry
                    Button(action: {
                        isPresentingEntryEditView = true
                        selectedEntry = nil
                    })
                    {
                        VStack
                        {
                            Image(systemName: "plus.circle") //.fill")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 25, height: 25)
//                            Text("Add Entry")
//                                .font(.system(size: 14))
                        }
                    }
                    // Delete Entries
                    Button(action: {
                        isPresentingDeleteView = true
                    })
                    {
                        VStack
                        {
                            Image(systemName: "trash.circle") //.fill")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 25, height: 25)
                        }
                    }
                    // Accounts
                    Button(action: {
                        isPresentingAccountsView = true
                    })
                    {
                        VStack
                        {
                            Image(systemName: "building.columns.circle") //.fill")
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 25, height: 25)
                        }
                    }
                }

                EntryListView(entries: entries, selectedEntry: $selectedEntry, bindTotalAmount: $finalAmount, updateTotalAmount: calculateTotalAmount)
                { totalAmount in
                    // Update the totalAmount in the ContentView
                    finalAmount = totalAmount
                }
                .onAppear 
                {
                    // Calculate totalAmount when the view appears initially
                    finalAmount = calculateTotalAmount()
                }
                .onReceive(NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave)) { _ in
                    // Calculate totalAmount when the managed object context is saved (i.e., an entry is added or edited)
                    finalAmount = calculateTotalAmount()
                }
                .onTapGesture
                {
                    isPresentingEntryEditView = true
                }
                    //.padding(.top, 20)
                
                //Display the grand total at the bottom of the screen
                HStack
                {
                    //"$\(entry.cftAmount, specifier: "%.2f")"
                    Text("Projected Total $\(finalAmount, specifier: "%.2f")")
                        .font(.title3)
                        .fontWeight(.regular)
                        .padding(.trailing, 10)
                }
            }
            .sheet(isPresented: $isPresentingEntryEditView) 
            {
                EntryEditView(selectedEntry: $selectedEntry, bindTotalAmount: $finalAmount, selectedAccount: $selectedAccount)
            }
            .sheet(isPresented: $isPresentingSettingsView) 
            {
                EntrySettingsView()
            }
            .sheet(isPresented: $isPresentingDeleteView)
            {
                DeleteEntriesView()
            }
            .sheet(isPresented: $isPresentingAccountsView)
            {
                // Pass selectedAccount as binding
                SelectAccountView(selectedAccount: $selectedAccount)
            }
        }
    }
    
    func calculateTotalAmount() -> Float
    {
        var calculatedTotalAmount: Float = 0.0
        
        let filteredEntries: [CFTEntry]
        if let selectedAccount = selectedAccount
        {
            filteredEntries = entries.filter { $0.cftAccount == selectedAccount.cftAccount }
        } 
        else
        {
            filteredEntries = entries.map { $0 }
        }
        for entry in filteredEntries 
        {
            if entry.cftCategory == "Income"
            {
                calculatedTotalAmount += entry.cftAmount
            }
            else
            {
                calculatedTotalAmount -= entry.cftAmount
            }
        }
       
        return calculatedTotalAmount
    }
}

核心数据实体是CFTEntry,它包含属性cftAccount。每次用户显示SelectAccountView选择账户时,代码中都成功检索到账户名

Text("Account: \(account.cftAccount ?? "")")

在 ContentView 中,我将 entries 变量传递给 EntryListView,它在其中显示 CFTEntry 记录列表。如何按 selectedAccount 进行过滤?

swiftui core-data
1个回答
0
投票

我通过重新安排过滤过程解决了我的问题。不需要在ContentView@FetchRequest,因为在ContentViewSelectAccountView之间来回处理比较麻烦。由于 ContentView 已经捕获了 selectedAccount 值,因此我将其作为参数传递给 EntryListView 并在内部执行过滤。

© www.soinside.com 2019 - 2024. All rights reserved.