I have a view that outputs rows of data using ForEach. The data is an array of defined data records from an FMDB database. I use List / ForEach and LazyVGrid to populate the rows in the view.
My goal is to take two of the output fields in the LazyVGrid and use onGesture to invoke one of two .sheet views for the details behind the value.
In the onGesture I want to capture the dataRecord used to populate that row and use the data in that record to call the view in .sheet
It all seems to work until I get to the .sheet(isPresented... There the @State variable I populate in the onGesture is Nil
I'm putting in the code I use along with some print output that seems to show that the @State variable is populated in onGesture, but later in the .sheet(isPresented it is nil
I'm not sure I understand the scope of visibility for that @State variable and wonder if someone can help me figure this out...
MY CODE IS:
import SwiftUI
struct BudgetedIncomeView: View {
@State var account_code: Int
@State var budgetYear: Int
@State var budgetMonth: Int
@State private var isAdding = false
@State private var isEditing = false
@State private var isDeleting = false
@State private var budgetRec = BudgetedIncome.BudgetedIncomeRecord()
@State private var isBudgeted = false
@State private var isReceived = false
// Environment and ObservedObjects
@Environment(\.presentationMode) var presentationMode
@Environment(\.editMode) var editMode
@StateObject var toolbarViewModel = ToolbarViewModel()
var displayMonthYearString: String {
return calendarMonths(budgetMonth) + "-" + String(budgetYear)
}
let columns = [
GridItem(.flexible(), alignment: .leading),
GridItem(.fixed(UIScreen.main.bounds.width * 0.20), alignment: .trailing),
GridItem(.fixed(UIScreen.main.bounds.width * 0.20), alignment: .trailing)
]
let numberColor = Color.black
let negativeColor = Color.red
// Array of Budgeted Income records for View List
var budgetedIncome: [BudgetedIncome.BudgetedIncomeRecord] {
return BudgetedIncome.shared.selectBudgetedIncomeForAccountWithMonthAndYear(withAccountCode: self.account_code, withYear: self.budgetYear, withMonth: self.budgetMonth)
}
var body: some View {
ZStack {
VStack {
BudgetedIncomeHeader(headerText: "Budgeted")
.padding(.top, 10)
List {
ForEach (self.budgetedIncome, id: \.self) { budgetRecord in
LazyVGrid(columns: columns, spacing: 5) {
Text("\(budgetRecord.description)")
.lineLimit(1)
.padding(.leading, 5)
Text("\(NumberFormatter.formatWithComma(value: budgetRecord.income_budget))")
.foregroundColor((budgetRecord.income_budget < 0 ) ? self.negativeColor : self.numberColor)
.onTapGesture {
//
// PRINT STATEMENTS THAT SHOW THE DATA IS CAPTURED
//
let _ = print("budgetRecord in onGesture = \(budgetRecord)\n\n")
budgetRec = budgetRecord
let _ = print("budgetRec in onGesture = \(budgetRec)\n\n")
isBudgeted.toggle()
}
Text("\(NumberFormatter.formatWithComma(value: budgetRecord.income_received))")
.underline()
.padding(.trailing, 15)
}// END OF LAZYVGRID
} // END OF FOREACH
} // END OF LIST
BudgetedIncomeFooter(accountCode: $account_code, budgetYear: $budgetYear, budgetMonth: $budgetMonth)
.padding(.top, 5)
} // END OF VSTACK
.sheet(isPresented: $isBudgeted ){
//
// PRINT STATEMENT THAT SHOWS THE DATA IS NIL HERE
//
let _ = print("budgetRec in .sheet = \(budgetRec)\n\n")
BudgetedIncomeDetailsView(accountCode: budgetRec.account_code, incomeCode: budgetRec.income_code, budgetYear: budgetRec.budget_year, budgetMonth: budgetRec.budget_month)
.opacity(isBudgeted ? 1 : 0)
.zIndex(isBudgeted ? 1 : 0)
}
if isReceived {
BudgetedIncomeDetailsView(accountCode: 12345678, incomeCode: 50060, budgetYear: 2020, budgetMonth: 12)
.opacity(isReceived ? 1 : 0)
.zIndex(isReceived ? 1 : 0)
}
} // END OF ZSTACK
.navigationTitle("Budgeted Income for \(self.displayMonthYearString)")
.navigationBarBackButtonHidden(true)
.toolbar {
ToolBarCancelDeleteAdd() {
toolbarViewModel.cancelContent(editMode: editMode)
presentationMode.wrappedValue.dismiss()
}
adding: {
toolbarViewModel.addingContent(isAdding: &isAdding, editMode: editMode)
}
} // END OF TOOLBAR
} // END OF BODY VIEW
} // END OF STRUCT VIEW
struct BudgetedIncomeView_Previews: PreviewProvider {
static var previews: some View {
BudgetedIncomeView(account_code: 12345678,
budgetYear: 2020,
budgetMonth: 12)
.environmentObject(ApplicationSettings())
.environmentObject(Budget())
.environmentObject(GlobalSettings())
}
}
The output from these print statements is:
budgetRecord in onGesture = BudgetedIncomeRecord(income_id: Optional(589), account_code: Optional(12345678), income_code: Optional(50060), budget_year: Optional(2020), budget_month: Optional(12), description: Optional("ADD BACK SET ASIDE"), category: Optional("*Exclude From Reports"), income_budget: Optional(3600.0), income_received: Optional(3600.0), unexpected_income: Optional(0.0), category_code: Optional(99999), set_aside: Optional(true), set_aside_id: nil)
budgetRec in onGesture = BudgetedIncomeRecord(income_id: Optional(589), account_code: Optional(12345678), income_code: Optional(50060), budget_year: Optional(2020), budget_month: Optional(12), description: Optional("ADD BACK SET ASIDE"), category: Optional("*Exclude From Reports"), income_budget: Optional(3600.0), income_received: Optional(3600.0), unexpected_income: Optional(0.0), category_code: Optional(99999), set_aside: Optional(true), set_aside_id: nil)
budgetRec in .sheet = BudgetedIncomeRecord(income_id: nil, account_code: nil, income_code: nil, budget_year: nil, budget_month: nil, description: nil, category: nil, income_budget: nil, income_received: nil, unexpected_income: nil, category_code: nil, set_aside: nil, set_aside_id: nil)
It seems to me that somewhere the data goes nil. I don't seem to follow where the data is going out of scope???
I have used this technique in other views where I have used a view for the row and let the whole row be selected .onGesture.
I haven't tried it using LazyVGrid and selecting specific output values..
Any help would be greatly appreciated..
Bob