我正在使用 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 进行过滤的尝试都没有成功。我非常感谢您帮助解决这个问题。
提前谢谢您
我通过重新安排过滤过程解决了我的问题。不需要在ContentView中@FetchRequest,因为在ContentView和SelectAccountView之间来回处理比较麻烦。由于 ContentView 已经捕获了 selectedAccount 值,因此我将其作为参数传递给 EntryListView 并在内部执行过滤。