如何使 shortcut/binding 成为 class 中的结构? (斯威夫特用户界面)

How to make shortcut/binding to a struct inside class? (SwiftUI)

在我的 class 中,我有一个 Item 数组和一个可选的变量 selection,它应该存储所选项目的快捷方式。 我需要能够通过引用 selection.

访问所选项目

为了让选择作为快捷方式工作,选择必须是 Binding 吗? 如果是,它是像结构中的 @Binding,还是 Binding<T>? 它必须是 @Published 吗?

我的代码:

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())
        }
    }
}

所需功能:点击其中一项,然后为其着色。

因为您希望选择是“....数组中的选定项目”,那么您可以 只需使用项目数组中的索引。是这样的: (虽然你的代码逻辑对我来说有点奇怪,但我认为这只是一个测试例子)

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())
        }
    }
}