I'm working through the 100 days of SwiftUI. I'm working on the iExpense app and I'm attempting to make it so that when you click on an item's "edit" button, you can visit the AddItem
view and rather than make a new expense, you'll edit the existing one. I'm doing this by tracking an optional editId
. What I noticed is that if I launch the app and restart it and then attempt to edit an existing item that was recalled from UserData
, it for some reason thinks the editId
is nil
. At first I thought maybe my expense id
values were not getting stored correctly or getting out of sync but I added a number of print
statements and verified they are in fact in sync. What's odd though, is if I add this statement to the top of ContentView
's body
if let editId = self.editId {
print("edit id: \(editId)")
}
And then immediately return my view, it always works. That is to say, it always seems to recognize the correct editId
. However, the second I remove that, it no long works. Here's the complete code for ContentView
for context (note: the trailing closure for .sheet()
is where the editId
is sometimes right/wrong)
import SwiftUI
struct ContentView: View {
@ObservedObject var expenses: Expenses = Expenses()
@State private var showingAddExpense = false
@State private var editId: UUID?
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
var body: some View {
/*
* For some reason, if i I don't attempt to unwrap the self.editId
* here then initially when you try to edit an existing item,
* it will be treated as nil. :shrug:
*/
if let editId = self.editId {
print("edit id: \(editId)")
}
return NavigationView {
List {
ForEach(expenses.items) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)
.font(.headline)
Text(item.type)
Text("\(item.id)")
.font(.footnote)
}
Spacer()
Text("$\(item.amount)")
Button("Edit") {
self.showingAddExpense = true
self.editId = item.id
}
}
.padding()
.background(item.amount > 100 ? Color.red : item.amount > 50 ? Color.yellow : item.amount > 10 ? Color.green : nil)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("iExpense")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
HStack {
Button(action: {
self.editId = nil
self.showingAddExpense = true
}) {
Image(systemName: "plus")
}
}
}
ToolbarItem(placement: .navigationBarLeading) {
EditButton()
}
}
}
.sheet(isPresented: $showingAddExpense) {
// This is where self.editId will be nil if I do not include the if expression at the top
AddView(expenses: self.expenses, editId: self.editId)
}
}
}
If you need additional context or other parts of the code, I'm happy to paste it in