In my class, I have an array of Item
and an optional var selection
, which is supposed to store a SHORTCUT to the selected Item.
I need to be able to access the selected Item by referring to selection
.
In order for selection to work as SHORTCUT does selection has to be a Binding
?
If yes, is it a @Binding
like in structs, or maybe Binding<T>
?
And does it has to be @Published
?
My code:
import SwiftUI
struct Item: Identifiable, Equatable {
var id = UUID().uuidString
var color: Color
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(color: .blue), Item(color: .blue), Item(color: .blue)]
@Published var selection: Item? //this supposed to be not a value, but a SHORTCUT to a selected item inside array
func setSelection (item: Item) {
selection = item
}
func changeColor (color: Color) {
if selection != nil {
selection?.color = color// << PROBLEM is that it only copies object and modifies the copy instead of original
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
//list
VStack {
ForEach(model.items.indices, id:\.hashValue) { i in
SubView(item: $model.items[i], model: model)
}
// change color button
Button {
model.changeColor(color: .red)
} label: {Text("Make Selection Red")}
}.padding()
}
}
struct SubView: View {
@Binding var item: Item
var model: Model
var body: some View {
VStack {
// button which sets selection to an items inside this subview
Button {
model.setSelection(item: item)
} label: {
Text("Select").background(item.color)}.buttonStyle(PlainButtonStyle())
}
}
}
Desired functionality: click on one if items, and then charging its color.
since you want selection to be "....a selected item inside array", then you could just use the index in the array of items. Something like this: (although your code logic is a bit strange to me, I assumed this is just a test example)
struct Item: Identifiable, Equatable {
var id = UUID().uuidString
var color: Color
}
class Model: ObservableObject {
@Published var items: [Item] = [Item(color: .blue), Item(color: .blue), Item(color: .blue)]
@Published var selection: Int? // <-- here
func changeColor(color: Color) {
if let ndx = selection { // <-- here
items[ndx].color = color
}
}
}
struct ContentView: View {
@StateObject var model = Model()
var body: some View {
//list
VStack {
ForEach(model.items.indices, id:\.self) { i in
SubView(index: i, model: model) // <-- here
}
// change color button
Button {
model.changeColor(color: .red)
} label: {Text("Make Selection Red")}
}.padding()
}
}
struct SubView: View {
var index: Int // <-- here
@ObservedObject var model: Model // <-- here
var body: some View {
VStack {
// button which sets selection to an items inside this subview
Button {
model.selection = index
} label: {
Text("Select").background(model.items[index].color) // <-- here
}
.buttonStyle(PlainButtonStyle())
}
}
}