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.
CodePudding user response:
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())
}
}
}