具有不同存储属性的初始化程序



我有以下视图,在其中我将绑定传递给需要选择的项。

struct SelectionListView<Data>: View where Data: RandomAccessCollection, Data.Element: Identifiable, Data.Element: Named {
private let data: Data
@Binding private var isPresented: Bool
@Binding private var selectedElement: Data.Element
init(
data: Data,
selectedElement: Binding<Data.Element>,
isPresented: Binding<Bool>
) {
self.data = data
_selectedElement = selectedElement
_isPresented = isPresented
}

var body: some View {
VStack {
ForEach(data) { element in
Button(element.name) {
selectedElement = element
isPresented.toggle()
}
.foregroundColor(
selectedElement.id == item.id
? .black
: .white
)
}
}
}
}

我需要一个稍微不同的视图初始值设定项,在这里我只能传递元素ID,而不能传递整个元素。我很难实现这个解决方案。更清楚地说,如果我能有第二个初始化器,那就太好了,比如:

init(
data: Data,
selectedId: Binding<Data.Element.ID>,
isPresented: Binding<Bool>
)

这是一个工作版本。我决定将elementid存储在它们自己的枚举案例中。我把观点分开,只是为了更容易理解我所做的事情。

工作代码:

struct SelectionListView<Data>: View where Data: RandomAccessCollection, Data.Element: Identifiable, Data.Element: Named {

enum Selected {
case element(Binding<Data.Element>)
case id(Binding<Data.Element.ID>)
}

@Binding private var isPresented: Bool
private let data: Data
private let selected: Selected

init(
data: Data,
selectedElement: Binding<Data.Element>,
isPresented: Binding<Bool>
) {
self.data = data
selected = .element(selectedElement)
_isPresented = isPresented
}

init(
data: Data,
selectedId: Binding<Data.Element.ID>,
isPresented: Binding<Bool>
) {
self.data = data
selected = .id(selectedId)
_isPresented = isPresented
}

var body: some View {
SelectionListItem(data: data) { dataElement in
switch selected {
case .element(let element):
element.wrappedValue = dataElement
print("Selected element:", element.wrappedValue)
case .id(let id):
id.wrappedValue = dataElement.id
print("Selected element ID:", id.wrappedValue)
}

isPresented.toggle()
}
}
}

struct SelectionListItem<Data>: View where Data: RandomAccessCollection, Data.Element: Identifiable, Data.Element: Named {
let data: Data
let action: (Data.Element) -> Void

var body: some View {
VStack {
ForEach(data) { element in
Button(element.name) {
action(element)
}
.foregroundColor(
.red  // Temporary because I don't know what `item.id` is
//                    selectedElement.id == item.id
//                        ? .black
//                        : .white
)
}
}
}
}

最小工作示例的其他代码:

struct ContentView: View {

@State private var selection: StrItem
@State private var selectionId: StrItem.ID
@State private var isPresented = true
private let data: [StrItem]

init() {
data = [StrItem("Hello"), StrItem("world!")]
_selection = State(initialValue: data.first!)
_selectionId = State(initialValue: data.first!.id)
}

var body: some View {
// Comment these to try each initializer
//SelectionListView(data: data, selectedElement: $selection, isPresented: $isPresented)
SelectionListView(data: data, selectedId: $selectionId, isPresented: $isPresented)
}
}
protocol Named {
var name: String { get }
}
struct StrItem: Identifiable, Named {
let id = UUID()
let str: String
var name: String { id.uuidString }

init(_ str: String) {
self.str = str
}
}

我真的不确定你想要实现什么。有些东西感觉不对劲:(但无论如何,这里有一个你的代码变体,可以做你想做的事:

struct SelectionListView<Data>: View where Data: RandomAccessCollection, Data.Element: Identifiable, Data.Element: Named {
private let data: Data
@Binding private var isPresented: Bool
@Binding private var selectedElement: Data.Element
@Binding private var selectedId: Data.Element.ID

init(
data: Data,
selectedElement: Binding<Data.Element>,
isPresented: Binding<Bool>
) {
self.data = data
_selectedElement = selectedElement
_selectedId = .constant(selectedElement.wrappedValue.id)
_isPresented = isPresented
}

init(
data: Data,
selectedId: Binding<Data.Element.ID>,
isPresented: Binding<Bool>
) {
self.data = data
_selectedElement = .constant(data.first(where: { $0.id == selectedId.wrappedValue })!)
_selectedId = selectedId
_isPresented = isPresented
}

var body: some View {
VStack {
ForEach(data) { element in
Button(element.name) {
selectedElement = element
selectedId = element.id
isPresented.toggle()
}
.foregroundColor(
selectedElement.id == element.id
? .black
: .gray
)
}
}
}
}

最新更新