我希望在更改pickerSelectedItem时更新列表。我还是Swift的新手。我有一个提取行的函数,但是我觉得如果列表是@State对象,我不需要每次列表更新时都运行该函数。我的想法正确吗?有没有更好的方法来创建/调用此列表,以便它动态更新?
我正在调用的editExpense表存在类似问题。工作表解散后,我需要致电fetchRows。
import SwiftUI
import CoreData
@available(iOS 14.0, *)
struct ExpenseList: View {
@State var editExpense: Expenses?
@State var addExpense = false
@Environment(\.managedObjectContext)
var context: NSManagedObjectContext
@FetchRequest(fetchRequest: Expenses.expensesList)
private var result: FetchedResults<Expenses>
@State var expensesList: [ExpensesList]?
@State var sortedExpensesList: [ExpensesList]?
@State var pickerSelectedItem = 0
var body: some View {
VStack{
Picker(selection: $pickerSelectedItem, label: Text("")) {
Text("One-time").tag(0)
Text("Recurring").tag(1)
}
.pickerStyle(SegmentedPickerStyle())
.padding(.horizontal, 24)
if expensesList != nil{
List{
ForEach(self.sortedExpensesList!) { log in
Button(action: {
self.editExpense = getExpenseFromExpenseList(id: log.id)
}) {
ExpenseRow(name: log.expense, date: log.date, amount: log.cost, account: log.account)
}
}.onDelete(perform: onDelete)
}.environment(\.defaultMinListRowHeight, 5)
}else {
Text("No One-time Expenses in this date range")
}
Spacer()
HStack{
Spacer()
Button(action: {
self.addExpense.toggle()
}, label: {
Image(systemName: "plus.circle.fill").font(.system(size: 30))
}).padding(.all, 20)
}
}.onAppear(perform: fetchRows)
.navigationBarItems(trailing:
Button(action: {
self.addExpense.toggle()
}, label: {
Image(systemName: "plus.circle.fill").font(.system(size: 30))
}))
.sheet(item: $editExpense, onDismiss: {
self.editExpense = nil
})
{
(log: Expenses) in
Print("ID: \(log.id)")
ExpenseDetail(
//context: self.context,
editExpense: log,
name: log.expenseName ?? "",
amount: String(log.expenseCost),
category: log.expenseCategory ?? "",
date: log.expenseDate ?? Date(),
account: log.expenseAccount ?? "",
expenseType: log.expenseType ?? "",
titleType: "",
types: ["One-time","Monthly","Per Paycheck","Weekly"]
).environment(\.managedObjectContext, self.context).onDisappear(perform: fetchRows)
}
.background(EmptyView()
.sheet(isPresented: $addExpense, content: {
ExpenseDetail(titleType: "", types: ["One-time"]).environment(\.managedObjectContext, context).onDisappear(perform: fetchRows)
}))
}
func fetchRows(){
let predicate: NSPredicate
if self.pickerSelectedItem == 0{
predicate = NSPredicate(format: "expenseDate >= %@ AND expenseDate < %@ AND expenseType == %@", PayScheduleForm().currentPayDate as NSDate, PayScheduleForm().nextPaydate as NSDate, "One-time")
} else{
predicate = NSPredicate(format: "expenseDate >= %@ AND expenseDate < %@ AND expenseType != %@", PayScheduleForm().currentPayDate as NSDate, PayScheduleForm().nextPaydate as NSDate, "One-time")
}
Expenses.fetchAllExpensesInDateRange(context: self.context, predicate: predicate) { (results) in
guard !results.isEmpty else {
self.expensesList = nil
return
}
self.expensesList = results.map({ (result) -> ExpensesList in
// print(result.self)
return ExpensesList(id: result.id, isPaid: result.expenseIsPaid, expense: result.expenseName, cost: result.expenseCost, account: result.expenseAccount, date: result.expenseDate,expenseType: result.expenseType)
})
self.sortedExpensesList = self.expensesList?.sorted{
$0.date < $1.date
}
}
}
func getExpenseFromExpenseList(id: UUID) -> Expenses{
var expenses: Expenses?
let request = NSFetchRequest<NSFetchRequestResult>(entityName: Expenses.entity().name ?? "Expenses")
request.predicate = NSPredicate(format: "id == %@", id as CVarArg)
do {
let result = try context.fetch(request)
for data in result as! [Expenses] {
expenses = data.self
return expenses ?? Expenses.init()
}
} catch {
print("Fetch failed")
}
return expenses ?? Expenses.init()
}
struct ExpenseList_Previews: PreviewProvider {
static var previews: some View {
return ExpenseList()
}
}
private func onDelete(with indexSet: IndexSet) {
indexSet.forEach { index in
let listItem = sortedExpensesList![index]
print("listItem : \(listItem.id)")
let log = getExpenseFromExpenseList(id: listItem.id)
print("Expenses Object ID: \(log.id)")
if listItem.id == log.id{
context.delete(log)
print("trying to delete...")
try? context.saveContext()
fetchRows()
}else {
print("ID's don't match")
}
}
}
}
struct ExpensesList: Identifiable, Equatable {
let id: UUID
let isPaid: Bool
let expense: String
let cost: Double
let account: String
let date: Date
let expenseType: String
}
extension View {
func Print(_ vars: Any...) -> some View {
for v in vars { print(v) }
return EmptyView()
}
}