I'm working on an app where I have a view AddMonthView where you put in the monthly balance for financial accounts. That account list is dynamic. So I spent some time trying to figure out how to bind the balance input for each Account and got to a point where the UI works and it looks like the binding works however when I click into a TextField it creates a new duplicate line item with the same account name and balance number and I don't know why this is happening. If I click back into either of those line items then it modifies the other and never creates a third duplicate line item. Another issue I'm seeing is when I try to default a balance amount in the init it doesn't actually set that value and instead the UI is showing it as nil. I'm not sure, but guessing the issue could be with this line: _accountBalances = State(initialValue: tempAccountBalances) but I don't know if there is another way I should be initializing a @State property with passed in data. For what it's worth accounts can also be queried. Currently it's being queried in the parent view and being passed in.
EDIT: I tried updating my Dictionary to be [String : Double] and that seemed to fix the duplication issue, so it must be with my Account model?
import Foundation
import SwiftData
import SwiftUI
struct AddMonthView: View {
@Environment(\.modelContext) private var modelContext
@Binding var showAddMonth: Bool
@State var accountBalances = [Account : Double]()
init (showAddMonth: Binding<Bool>, accounts: [Account], date: Date) {
self._showAddMonth = showAddMonth
var tempAccountBalances = [Account: Double]()
for account in accounts {
tempAccountBalances[account] = 13 //defaulting to any number doesn't appear to work
}
_accountBalances = State(initialValue: tempAccountBalances)
}
var body: some View {
NavigationStack {
Form {
List {
ForEach(accountBalances.keys.sorted(), id: \.self) {account in
HStack {
Text(account.name)
.frame(maxWidth: .infinity, alignment: .leading)
TextField(value: $accountBalances[account], format: .currency(code: Locale.current.currency?.identifier ?? "USD")) {
Text("Balance")
}
.keyboardType(.decimalPad)
.submitLabel(.done)
}
}
}
}
.navigationTitle("New Month").navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .topBarTrailing) {
Button(action: saveMonth) {
Label("Add Month", systemImage: "checkmark")
}
}
ToolbarItem(placement: .topBarLeading) {
Button("Cancel", role: .cancel) {
self.showAddMonth.toggle()
}
}
}
}
}
func saveMonth() {
}
}
#Preview {
let date = Calendar.current.date(byAdding: .year, value: 1, to: Date())
AddMonthView(showAddMonth: .constant(true), accounts: Account.sampleData, date: Date())
.modelContainer(SampleData.shared.modelContainer)
}

id: \.selfin theForEach, try to remove altogether or replace it withid: \.id(I am assuming Account is a SwiftData model)id: \.idand completely removing it yields the same duplicate result. Interestingly though the more I test this it seems like sometimes random values will get the default I set in theinitand when I modify those they don't duplicate