如何使用ForEach Identifiable SwiftUI更改按钮按下时的值



我正在为IOS开发应用程序,我是第一次使用SwiftUI,只是一个初学者。问题是,我试图通过使用ForEach Identifiable按钮单击来更改Text((的值。一切都很好,但这是我唯一不能做的事情,也不能在互联网上为自己找到答案。

这是应用的观点

这是我的代码


import SwiftUI
private struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) {}
}
public struct SemaphoreFlags: View {
@State private var headerHeight = CGSize()

public var body: some View {
ZStack{

Image("background")
.resizable()
.scaledToFill()
.frame(maxWidth: UIScreen.screenWidth, maxHeight: UIScreen.screenHeight )
.edgesIgnoringSafeArea(.bottom)

VStack{

Image("header_inv")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: UIScreen.screenWidth ,alignment: .top)
.opacity(0.0)
.readSize {
height in headerHeight = height
}.padding(.bottom, 16)

Text("HEADER TEXT")
.foregroundColor(.white)
.font(.system(size: 24))
.fontWeight(.medium)
.frame(width: UIScreen.screenWidth - 25, height: UIScreen.screenWidth / 6, alignment: .center)
.background(Color(red: 0.29, green: 0.67, blue: 0.88))
.padding(.bottom, 4.0)

ScrollView{
Text(NSLocalizedString("BeaufortScale_Description", comment: "BeaufortScale_Description"))
.font(.system(size: 20))
.multilineTextAlignment(.center)
.background(Color.white)
.padding(.horizontal,8)
.foregroundColor(.black)
.frame(width: .infinity, height: .infinity)

}

Image("blank")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: UIScreen.screenWidth - 25, height: UIScreen.screenWidth / 2, alignment: .center)


Text("BottomLETTER")
.font(.system(size: UIScreen.screenWidth/6))
.fontWeight(.medium)
.multilineTextAlignment(.center)
.foregroundColor(Color(red: 0.09, green: 0.30, blue: 0.47))
.frame(width: UIScreen.screenWidth, height: .infinity, alignment: .center)

Spacer()

ScrollView(.horizontal, showsIndicators: false){
HStack{
ForEach(semaphoreButtonPropsData) { item in
semaphoreFlagsButton(SemaphoreButtonProps: item)
}
}
}.clipped().edgesIgnoringSafeArea(.bottom).padding(.vertical)
}.frame(width: .infinity, height: .infinity)



Image("header")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: UIScreen.screenWidth, maxHeight: UIScreen.screenHeight ,alignment: .top)

VStack {
HStack {
Button (action: gotoMenu, label: {
Image("back")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 32, height: headerHeight.height)
.padding(.leading, 16.0)

})

Spacer()
}
Spacer()
}

}.background(Color(red: 0.09, green: 0.30, blue: 0.47).edgesIgnoringSafeArea(.all))
}
}
struct SemaphoreFlags_Previews: PreviewProvider {
static var previews: some View {
SemaphoreFlags()
}
}
struct semaphoreFlagsButton: View {
var SemaphoreButtonProps: semaphoreButtonProps
var body: some View {
Button(action:{
// ACTION TO CHANGE THE VALUES OF DESIGN 
(HEADER TEXT, DESCRIPTION, IMAGE, BOTTOM LETTER)
}, label: {
Text(SemaphoreButtonProps.buttonLetter)
.font(.system(size: 26))
.fontWeight(.light)
.foregroundColor(Color.white)
.multilineTextAlignment(.leading)
.padding(.all, 4.0)
.foregroundColor(.white)
.frame(width: .infinity, height: 50, alignment: .center)

})
.frame(width: 100, height: 50 , alignment: .center)
.background(Color(red: 0.29, green: 0.67, blue: 0.88))
.cornerRadius(12)
.padding(.leading, 8)
}
}
struct semaphoreButtonProps: Identifiable {
var id = UUID()
var headerText: String
var description: String
var image: Image
var bottomLetter: String
var buttonLetter: String
}
let semaphoreButtonPropsData = [
semaphoreButtonProps(headerText: "About",
description: NSLocalizedString("BeaufortScale_Description", comment: "BeaufortScale_Description"),
image: Image("blank"),
bottomLetter: " ",
buttonLetter: "About"),

semaphoreButtonProps(headerText: "Alpha",
description: " ",
image: Image("a-alpha"),
bottomLetter: "A",
buttonLetter: "A"),

semaphoreButtonProps(headerText: "Bravo",
description: " ",
image: Image("b-bravo"),
bottomLetter: "B",
buttonLetter: "B")
]

非常感谢!

为了使数据数组是可变的,它应该存储在View@State中。然后,您可以通过Binding将其传递给您的孩子View

(我还调整了类型的大小写以符合Swift惯例,所以如果复制/粘贴,请小心在代码中反映这一点(

public struct SemaphoreFlags: View {
@State private var semaphoreButtonPropsData = [ //<-- Here
SemaphoreButtonProps(headerText: "About",
description: NSLocalizedString("BeaufortScale_Description", comment: "BeaufortScale_Description"),
image: Image("blank"),
bottomLetter: " ",
buttonLetter: "About"),

SemaphoreButtonProps(headerText: "Alpha",
description: " ",
image: Image("a-alpha"),
bottomLetter: "A",
buttonLetter: "A"),

SemaphoreButtonProps(headerText: "Bravo",
description: " ",
image: Image("b-bravo"),
bottomLetter: "B",
buttonLetter: "B")
]

public var body: some View {
ScrollView(.horizontal, showsIndicators: false){
HStack{
ForEach($semaphoreButtonPropsData) { $item in //<-- Here
SemaphoreFlagsButton(semaphoreButtonProps: $item) //<-- Here
}
}
}
}
}
struct SemaphoreFlagsButton: View {
@Binding var semaphoreButtonProps: SemaphoreButtonProps //<-- Here
var body: some View {
Button(action:{
semaphoreButtonProps.buttonLetter = "(Date())" //<-- Here
}, label: {
Text(semaphoreButtonProps.buttonLetter)
})
.frame(width: 100, height: 50 , alignment: .center)
.background(Color(red: 0.29, green: 0.67, blue: 0.88))
.cornerRadius(12)
.padding(.leading, 8)
}
}
struct SemaphoreButtonProps: Identifiable { //<-- Here
var id = UUID()
var headerText: String
var description: String
var image: Image
var bottomLetter: String
var buttonLetter: String
}

更新,基于询问者的新信息:

public struct SemaphoreFlags: View {
@State private var headerText : String = "HEADER TEXT"
@State private var semaphoreButtonPropsData = [ //<-- Here
SemaphoreButtonProps(headerText: "About",
description: NSLocalizedString("BeaufortScale_Description", comment: "BeaufortScale_Description"),
image: Image("blank"),
bottomLetter: " ",
buttonLetter: "About"),

SemaphoreButtonProps(headerText: "Alpha",
description: " ",
image: Image("a-alpha"),
bottomLetter: "A",
buttonLetter: "A"),

SemaphoreButtonProps(headerText: "Bravo",
description: " ",
image: Image("b-bravo"),
bottomLetter: "B",
buttonLetter: "B")
]

public var body: some View {
Text(headerText)
ScrollView(.horizontal, showsIndicators: false){
HStack{
ForEach(semaphoreButtonPropsData) { item in //<-- Here
SemaphoreFlagsButton(semaphoreButtonProps: item, headerText: $headerText) //<-- Here
}
}
}
}
}
struct SemaphoreFlagsButton: View {
var semaphoreButtonProps: SemaphoreButtonProps
@Binding var headerText : String
var body: some View {
Button(action:{
headerText = semaphoreButtonProps.headerText
}, label: {
Text(semaphoreButtonProps.buttonLetter)
})
.frame(width: 100, height: 50 , alignment: .center)
.background(Color(red: 0.29, green: 0.67, blue: 0.88))
.cornerRadius(12)
.padding(.leading, 8)
}
}
struct SemaphoreButtonProps: Identifiable { //<-- Here
var id = UUID()
var headerText: String
var description: String
var image: Image
var bottomLetter: String
var buttonLetter: String
}

或者,一个存储所选项目ID的选项:

public struct SemaphoreFlags: View {
@State private var selectedSemaphore : UUID? = nil
@State private var semaphoreButtonPropsData = [ //<-- Here
SemaphoreButtonProps(headerText: "About",
description: NSLocalizedString("BeaufortScale_Description", comment: "BeaufortScale_Description"),
image: Image("blank"),
bottomLetter: " ",
buttonLetter: "About"),

SemaphoreButtonProps(headerText: "Alpha",
description: " ",
image: Image("a-alpha"),
bottomLetter: "A",
buttonLetter: "A"),

SemaphoreButtonProps(headerText: "Bravo",
description: " ",
image: Image("b-bravo"),
bottomLetter: "B",
buttonLetter: "B")
]

public var body: some View {
if let selected = semaphoreButtonPropsData.first(where: { $0.id == selectedSemaphore }) {
Text(selected.headerText)
}
ScrollView(.horizontal, showsIndicators: false){
HStack{
ForEach(semaphoreButtonPropsData) { item in //<-- Here
SemaphoreFlagsButton(semaphoreButtonProps: item, selectedSemaphore: $selectedSemaphore) //<-- Here
}
}
}
}
}
struct SemaphoreFlagsButton: View {
var semaphoreButtonProps: SemaphoreButtonProps
@Binding var selectedSemaphore : UUID?
var body: some View {
Button(action:{
selectedSemaphore = semaphoreButtonProps.id
}, label: {
Text(semaphoreButtonProps.buttonLetter)
})
.frame(width: 100, height: 50 , alignment: .center)
.background(Color(red: 0.29, green: 0.67, blue: 0.88))
.cornerRadius(12)
.padding(.leading, 8)
}
}

最新更新