I have a picker that will change an attribute of an object that is bound to the view. When the picker is changed I want to update the bound object so the change is apparent in the previous view. The picker updates the label on each change but the .onChanged modifier does’t fire after the first change. If changed 2 or more times the .onChanged body fires.
let categories: [String] = ["None", "Produce", "Dairy/Eggs", "Meat", "Breads", "Canned Goods", "Baking", "Frozen", "Bulk", "Snack Foods", "Spices/Seasonings", "Pasta/Rice", "Drinks", "Liquor", "Condiments"]
//Name of recipe received from previous view
@Binding var ingredient: Ingredient
//ingredient variable that can be updated
@State var category: String = ""
var body: some View {
VStack(alignment: .leading) {
Text(ingredient.name)
.font(.title)
.padding(.leading, 5)
Menu {
Picker("picker", selection: $category) {
ForEach(categories, id: .self) {
Text($0)
}
}
.onChange(of: category, perform: { newValue in
print("PICKER CHANGED")
ingredient.category = self.category
})
.labelsHidden()
.pickerStyle(InlinePickerStyle())
} label: {
Text(category)
.foregroundColor(.black)
.padding(5)
.labelsHidden()
.clipped()
.mask(RoundedRectangle(cornerRadius: 20, style: .continuous))
}
}
.onAppear(perform: {self.category = ingredient.category})
}
Ingredient class:
class Ingredient: Identifiable, Hashable{
static func == (lhs: Ingredient, rhs: Ingredient) -> Bool {
if (lhs.id == rhs.id) {return true}
else {return false}
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
}
public var id = UUID()
public var name: String = ""
public var inStock: Bool = false
public var category: String = ""
public var keepInStock: Bool = false
}
2
Answers
Have you tried setting a
tag
modifier on theText
property inside theForEach
for the picker?This issue is because SwiftUI does not know about the changes.
Ingredient
is aclass
change it to astruct
OR
make it an
ObservableObject
wrap the variables in@Published
and changeto
class
is reference type andstruct
is value type.@State
,@Binding
,@Published
see changes for value type.@ObservedObject
,@StateObject
, and@EnvironmentObject
are for reference. Accompanied byObservableObject
and@Published