'Picker not updating selection binding for Realm entities

I have a view that passes a binding to another view which includes a Picker. When an item is selected in the picker, the binding is not updated.

Here is the parent view:

struct AccountsView: View {
    
    @SceneStorage("selectedAccount") private var selectedAccount: String?
    @SceneStorage("isAddingAccount") private var isAddingAccount: Bool = false
    
    var body: some View {
        VStack {
            AccountsToolbar(selection: selectedAccountId, isAddingAccount: $isAddingAccount)
            if isAddingAccount {
                CreateAccountView(isAddingAccount: $isAddingAccount)
            }
        }
        .frame(maxHeight: .infinity, alignment: .topLeading)
    }
    
    var selectedAccountId: Binding<ObjectId?> {
        Binding(
            get: { selectedAccount == nil ? nil : try? ObjectId(string: selectedAccount!) },
            set: { print("new id: \($0)"); selectedAccount = String(describing: $0) }
        )
    }
    
}

...and the child view:

struct AccountsToolbar: View {
    
    @Binding var selection: ObjectId?
    @Binding var isAddingAccount: Bool
    @ObservedResults(Account.self) var accounts

    var body: some View {
        HStack {
            Picker("Account", selection: $selection) {
                ForEach(accounts, id: \.self) { account in
                    Text(account.name).tag(account._id)
                }
            }
            Button {
                isAddingAccount = true
            }
        label: {
            Image(systemName: "plus.circle.fill")
                .resizable()
                .foregroundStyle(.white, .indigo)
                .symbolRenderingMode(.palette)
                .frame(width: 20, height: 20)
        }
        .buttonStyle(.borderless)
        }
        .frame(height: 64)
    }
}

The Realm model looks like this:

class Account: Object, ObjectKeyIdentifiable {

    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var name: String
    @Persisted var apiKey: String
    @Persisted var privateKey: String

}

As I say, when an item is chosen from the Picker, the binding is not updated. The print in the set: of the binding in the AccountsView prints nil.

I have tried:

  • conforming the model to the Identifiable protocol
  • using a String? binding, rather than an ObjectId? binding
  • using Text(...).id(...) rather than Text(...).tag(...)
  • eliding the \.self in the ForEach

What might I be missing/doing wrong?



Solution 1:[1]

I found an answer here

I changed my Picker binding:

@Binding var selection: String?
...
Picker("Account", selection: $selection) {
    ForEach(accounts) { account in
        Text(account.name).tag(String?.some(String(describing: account._id)))
    }
}

It seems to work!

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 serlingpa