按下按钮后如何更改 SwiftUI 中的按钮

How do I change a button in SwiftUI after a button is pressed

我想要在按下按钮时将一张卡片图像更改为另一张卡片图像。这是我当前的代码:

import SwiftUI

var leftCard = "green_back"
var rightCard = "blue_back"

func dealCards() {
    leftCard = "1C"
    print("deal")
}

struct GameView: View {
    var body: some View {
        VStack {
            HStack(alignment: .center, spacing: 20) {
                Image(leftCard)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    
                Image(rightCard)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            .padding(.all, 25)
            
            Button(action: dealCards) {
                Text("Deal Cards")
                    .fontWeight(.bold)
                    .font(.title)
                    .padding(10)
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .padding(10)
                    .border(Color.blue, width: 5)
            }
        }
    }
}

struct GameView_Previews: PreviewProvider {
    static var previews: some View {
        GameView()
    }
}

当我按下按钮时,此代码会打印“deal”,但不会更改图像。

我正在使用 MacOS Big Sur beta 3 和 Xcode 12 beta 2。

编辑:我只需要将我的变量移动到 GameView 结构中并向它们添加一个 @State 修饰符。感谢所有回答的人。 :D

您可以将变量移动到 GameView 并添加 @State 修饰符:

struct GameView: View {
    @State var leftCard = "green_back"
    @State var rightCard = "blue_back"
    
    var body: some View {
        ...
    }
    
    func dealCards() {
        leftCard = "1C"
        print("deal")
    }
}

这样 SwiftUI 将在您的 @State 变量更改时刷新视图。

你甚至可以去掉函数,直接在按钮上添加代码

struct GameView: View {
    
    @State var leftCard = "green_back"
    @State var rightCard = "blue_back"
    
    var body: some View {
        VStack {
            HStack(alignment: .center, spacing: 20) {
                Image(leftCard)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                
                Image(rightCard)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            .padding(.all, 25)
            
            Button(action: {
                self.leftCard = "1C"
            }) {
                
                Text("Deal Cards")
                    .fontWeight(.bold)
                    .font(.title)
                    .padding(10)
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .padding(10)
                    .border(Color.blue, width: 5)
            }
        }
    }
}

以下代码应该会更新您的 Images 并且应该也会在 deal() 函数中为您提供一个随机值。

View 或组件中定义属性和函数非常重要。一般不建议使用全局变量,这可能会导致意外结果。

import SwiftUI

struct GameView: View {

    // 1. Add ImageName to handle names via dot (.) to avoid mistyping strings. CaseIterable allow you to get an array of all the values defined.
    enum ImageName: String, CaseIterable {
        case greenBack = "green_back"
        case blueBack = "blue_back"
        case other = "1C"
    }

    // 2. Add @State to update the GameView() automatically when any of the properties are updated.
    @State private var leftCard: ImageName = .greenBack
    @State private var rightCard: ImageName = .blueBack

    var body: some View {
        VStack {
            HStack(alignment: .center, spacing: 20) {

                // 3. Add .rawValue to get the raw String value
                Image(leftCard.rawValue)
                    .resizable()
                    .aspectRatio(contentMode: .fit)

                Image(rightCard.rawValue)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
            }
            .padding(.all, 25)

            Button(action: dealCards) {
                Text("Deal Cards")
                    .fontWeight(.bold)
                    .font(.title)
                    .padding(10)
                    .background(Color.blue)
                    .foregroundColor(.white)
                    .padding(10)
                    .border(Color.blue, width: 5)
            }
        }
    }

    func dealCards() {
        // 4. Update the name via dot(.) of any card that you want.
        // You can also randomise the card doing .allCases.randomElement()
        leftCard = ImageName.allCases.randomElement() ?? .greenBack
        print("deal")
    }
}

struct GameView_Previews: PreviewProvider {
    static var previews: some View {
        GameView()
    }
}