I have two structures. One of these structures Idea has a field that stores an instance of the other structure Option. In turn, Option has a list of IDs of Idea structures associated with it.
I created a Picker that onChange of Idea.Option adds the id of this idea to the list of associated ideas in Option.
This throws this error.

Here's the code
//ContentView
import SwiftUI
struct ContentView: View {
var options: [Option] = [
Option(name: "option1", assositatedIdea: []),
Option(name: "option2", assositatedIdea: []),
Option(name: "option3", assositatedIdea: [])
]
@Binding var ideas: Idea
var body: some View {
Picker("Option: \(ideas.option.name)", selection: $ideas.option) {
ForEach(options) {option in
Text(option.name).tag(option)
}
}.onChange(of: ideas.option) {newOption in
ideas.option.addAssosiatedIdea(ideaId: ideas.id)
}
}
}
struct Option: Hashable, Identifiable, Equatable {
let id: UUID
var name: String
var assositatedIdea: [UUID] // Stores IDs of structs of Ideas
init(id: UUID = UUID(), name: String, assositatedIdea: [UUID]) {
self.id = id
self.name = name
self.assositatedIdea = assositatedIdea
}
mutating func addAssosiatedIdea(ideaId: UUID) {
if (assositatedIdea.contains(ideaId)) {
return
}
self.assositatedIdea.append(ideaId)
}
}
extension Option {
static var emptyOption: Option {
Option(name: "", assositatedIdea: [])
}
}
struct Idea {
let id: UUID
var name: String
var option: Option
init(id: UUID = UUID(), name: String, option: Option) {
self.id = id
self.name = name
self.option = option
}
}
// test1App.swift
import SwiftUI
@main
struct test1App: App {
@State var ideas: Idea = Idea(name: "big brain idea", option: Option.emptyOption)
var body: some Scene {
WindowGroup {
ContentView(ideas: $ideas)
}
}
}
I want Picker to preview the new Option. However, Picker refresehs and displays the first Option in options.
I did some print debugging and found out that in fact, Idea gets its field updated.
Explanation
Firstly, here is an explanation for the error.
Optionhas an id of typeUUID.Optiontherefore has a unique but unpredictable id.Pickerusing an array ofOption, which is local to the viewContentView.Pickerto$ideas.option.Optionin the array, because it is sure to have its own unique id.Pickergives the error that "the selection [Option] is invalid and does not have an associated tag".Another reason why two
Optionwill probably not match is because eachOptionhas an array ofUUID. These are the ids of the associatedIdea.Quick fix
UUID, you could use a simpleInt. In order to ignore the associated ids, you should also implement your own equality function:ideaswith an empty option. So include an empty option in the list of pickable options:Alternative model
The changes above get it working, but it's still a bit messy. In particular, the way that
Optionholds a collection ofIdeaids means the two structs are inter-dependent.Here are some suggestions on how the data model and implementation could perhaps be made a bit cleaner:
letinstead ofvarwhenever possible.Ideaprobably doesn't need an id at all.The following illustrates how it can be implemented this way. The new type that models the relationship between
Optionand associatedIdeasisOptionAndIdeas, which is a class type. The classAllOptionsAndIdeasis a wrapper for a map of these classes.