Swift 具有不同存储属性的初始值设定项
我在下面的视图中向需要选择的项目传递绑定Swift 具有不同存储属性的初始值设定项,swift,swiftui,Swift,Swiftui,我在下面的视图中向需要选择的项目传递绑定 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 sele
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
)
}
}
}
}
struct SelectionListView:查看其中的数据:RandomAccessCollection,数据。元素:可识别,数据。元素:命名{
私人出租数据:数据
@绑定私有变量已呈现:Bool
@绑定私有变量selectedElement:Data.Element
初始化(
数据:数据,
selectedElement:绑定,
显示:绑定
) {
self.data=数据
_selectedElement=selectedElement
_isPresented=isPresented
}
var body:一些观点{
VStack{
ForEach(数据){元素在
按钮(element.name){
selectedElement=元素
isPresented.toggle()
}
.前底色(
selectedElement.id==item.id
黑色
怀特先生
)
}
}
}
}
我需要一个稍微不同的视图初始值设定项,在这里我只能传递元素ID,而不是整个元素。我很难实现这个解决方案。更清楚地说,如果我能有第二个初始值设定项,那就太好了:
init(
data: Data,
selectedId: Binding<Data.Element.ID>,
isPresented: Binding<Bool>
)
init(
数据:数据,
选择edid:Binding,
显示:绑定
)
这是一个工作版本。我决定将元素
或id
存储在它们自己的枚举案例中。我将视图分开,只是为了更容易理解我所做的
工作代码:
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 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
)
}
}
}
}
struct SelectionListView:查看其中的数据:RandomAccessCollection,数据。元素:可识别,数据。元素:命名{
私人出租数据:数据
@绑定私有变量已呈现:Bool
@绑定私有变量selectedElement:Data.Element
@绑定私有变量selectedId:Data.Element.ID
初始化(
数据:数据,
selectedElement:绑定,
显示:绑定
) {
self.data=数据
_selectedElement=selectedElement
_selectedId=.constant(selectedElement.wrappedValue.id)
_isPresented=isPresented
}
初始化(
数据:数据,
选择edid:Binding,
显示:绑定
) {
self.data=数据
_selectedElement=.constant(data.first(其中:{$0.id==selectedId.wrappedValue})!)
_selectedId=selectedId
_isPresented=isPresented
}
var body:一些观点{
VStack{
ForEach(数据){元素在
按钮(element.name){
selectedElement=元素
selectedId=element.id
isPresented.toggle()
}
.前底色(
selectedElement.id==element.id
黑色
格雷先生
)
}
}
}
}
您遇到了什么错误?类似于“无法分配给属性:'id'在尝试创建绑定id时是一个'let'常量”@George_E是的,但除此之外,我真的很想实现这两个初始化。如果您只传递id,您希望selectedElement=element
如何工作?@George_E我最好解释一下自己。如果我可以有两个不同的绑定,selectedElement
和selectedId
,并且有两个不同的初始值设定项来管理其中一个,那就太好了。解决方案是重写相同的视图以使用ids,但这会导致大量代码重复。因此,对于这种情况,您会选择selectedElement.id=element.id
?这是一个简单而优雅的解决方案。我很感激,谢谢。:)
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
)
}
}
}
}