0

I have a SwiftUI view with a Picker that lists a set of objects, whose id are of type UUIDs. For the purpose of reducing the example to the minimum code, I've represented the whole object as UUIDs. In the real application, the array of objects comes from the environment, but it is not important to the question.

When rendering the view, I get the following warning:

"Picker: the selection "nil" is invalid and does not have an associated tag, this will give undefined results."

How can I initialize the selected value for the picker, which is saved to SceneStorage, so that I get rid of the warning. In the example the saving to SceneStorage is useless, but in the real application is a requirement, so I cannot get rid of it.

Here is my code:

struct ContentView: View {
    
    private var values: [UUID] = [ UUID(), UUID()]
    
    @SceneStorage("VALUE") private var selectedValue: UUID?
        
    var body: some View {
        Form {
            Section("Test") {
                Picker("Select a value", selection: $selectedValue) {
                    //Text(values[0].uuidString).tag(values[0])
                    //Text(values[1].uuidString).tag(values[1])
                    ForEach(values, id: \.self) { value in
                        Text(value.uuidString).tag(value)
                    }
                }
                //.pickerStyle(.inline)
                .pickerStyle(.menu)
            }
        }
        .onAppear() {
            self.selectedValue = values[1] as UUID?
        }
    }
}

extension UUID: RawRepresentable {
    
    public typealias RawValue = String

    public init?(rawValue: RawValue) {
        self.init(uuidString: rawValue)
    }
    
    public var rawValue: String {
        self.uuidString
    }

}

My understanding is that the problem arises from the fact that the property selectedValue is Optional and SwiftUI is trying to render the view when its value has not yet been set. How can I get rid of the warning? Is there any way to initialize a SeceneStorage property value before onAppear, like on init?

I want to note also that such warning is not shown if the picker style is changed to .inline.

Thanks!

5
  • Why is the warning not shown then picketStyle is set to inline? Commented Oct 7, 2024 at 17:32
  • Yes, nil is not a valid option, however, the object with the initial value for the selectedValue property comes from the environment, which does not allow me to assign its value directly when declaring the selectedValue property, and assigning it in the onAppear shows this warning. Is there any other option? Commented Oct 7, 2024 at 17:47
  • To be honest, in the real application I'm facing a weird bug where the picker shows the first option as selected but clicking on the drop down of values shows the right value selected (which differs from the previous). Although I've not been able to create an minimum reproducible example of this, and I get the feeling that all problems are associated to that warning. Commented Oct 7, 2024 at 17:50
  • Wow, I tried your advice of surrounding the picker with "if selectedValue != nil" and solves both issues, the warning, and more importantly, the wierd bug I was facing. My conclusion though is that the Picker implentation has some wierd bug I did not got to properly isoltate to ba able to report, but after expending the whole day I think I'll comment the code properly and leave it like that. At least it works now. Thanks mate! Commented Oct 7, 2024 at 18:32
  • I have converted my comments into an answer. Commented Oct 7, 2024 at 18:39

1 Answer 1

1

You can wrap the Picker in an if selectedValue != nil { ... }. This prevents the whole picker from appearing when the selected value is nil, so obviously that warning will not appear.

if selectedValue != nil {
    Picker("Select a value", selection: $selectedValue) {
        // ...
    }
}

You can also get a non-optional Binding to the selected value, and use that instead,

if let binding = Binding($selectedValue) {
    Picker("Select a value", selection: $binding) {
        // ...
    }
}

For the toy example with UUIDs shown in the question, the warning will still appear on subsequent launches, because every time you are generating 2 new UUIDs, which will most definitely be different from the previous one stored in scene storage.

Sign up to request clarification or add additional context in comments.

1 Comment

The Picker bug is still there, but at least with that approach i can workaround it. Thansk Sweeper.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.