如何使用 ForEach Identifiable SwiftUI 更改按钮按下时的值
How to change value on button press using ForEach Identifiable SwiftUI
我正在为 IOS 开发应用程序,我是第一次使用 SwiftUI,只是一个初学者。
问题是我尝试通过使用 ForEach Identifiable 进行的按钮单击来更改 Text() 的值。一切都很好,但这是我唯一做不到的,只能在网上找到自己的答案。
This is the view of application
这是我的代码
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
将其传递给您的 child View
.
(我还调整了您的类型的大小写以适应 Swift 约定,所以如果您 copy/paste 时请小心在代码中反映这一点)
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: { [=12=].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)
}
}
我正在为 IOS 开发应用程序,我是第一次使用 SwiftUI,只是一个初学者。 问题是我尝试通过使用 ForEach Identifiable 进行的按钮单击来更改 Text() 的值。一切都很好,但这是我唯一做不到的,只能在网上找到自己的答案。
This is the view of application
这是我的代码
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
将其传递给您的 child View
.
(我还调整了您的类型的大小写以适应 Swift 约定,所以如果您 copy/paste 时请小心在代码中反映这一点)
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: { [=12=].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)
}
}