WWDC22 SALE: Save 50% on all my Swift books and bundles! >>

Picker not updating selection binding for Realm entities

Forums > SwiftUI

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?

   

Save 50% in my Black Friday sale.

SAVE 50% To celebrate WWDC22, all our books and bundles are half price, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.