You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI分值按钮异常:点击按钮却修改其他分值的问题求助

问题分析

你遇到的核心问题是所有按钮共享同一个showingAlert布尔状态变量。当任意按钮点击后将showingAlert设为true时,所有绑定该状态的.alert修饰符都会被触发,但SwiftUI无法区分当前弹窗是由哪个按钮触发的,最终会执行最后定义的弹窗动作(或因视图更新逻辑出现随机匹配其他分值的情况),这就导致了分值与按钮不对应的问题。

解决方案

改用可选类型的状态变量存储当前选中的分值,通过这个变量控制弹窗显示,并在弹窗中根据选中的分值执行分数增减操作,以此精准关联按钮与对应分值逻辑。

修改后的完整代码示例:

import SwiftUI

// 补充完整CurrentGameStatus定义
class CurrentGameStatus: ObservableObject {
    @Published var score = 0
}

struct ScoreHeader: View {
    @ObservedObject var gameStatus: CurrentGameStatus
    var body: some View {
        Text("Score: \(gameStatus.score)")
            .font(.title)
    }
}

struct QuestionValueButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .background(.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
    }
}

struct ContentView: View {
    // 用可选Int存储当前选中的分值,nil表示不显示弹窗
    @State private var selectedScore: Int?
    // 当前视图创建的ObservableObject推荐用@StateObject管理生命周期
    @StateObject var gameStatus = CurrentGameStatus()
    
    var body: some View {
        NavigationStack {
            HStack {
                VStack(spacing: 16) {
                    ScoreHeader(gameStatus: gameStatus)
                    
                    Button(action: { gameStatus.score = 0 }) {
                        Text("Reset Score")
                    }
                    
                    Button(action: { selectedScore = 200 }) { Text("200") }
                        .buttonStyle(QuestionValueButtonStyle())
                    
                    Button(action: { selectedScore = 400 }) { Text("400") }
                        .buttonStyle(QuestionValueButtonStyle())
                    
                    Button(action: { selectedScore = 600 }) { Text("600") }
                        .buttonStyle(QuestionValueButtonStyle())
                    
                    Button(action: { selectedScore = 800 }) { Text("800") }
                        .buttonStyle(QuestionValueButtonStyle())
                }
                // 统一绑定弹窗状态,仅需一个.alert修饰符
                .alert("Did you get the question right?", isPresented: .constant(selectedScore != nil)) {
                    Button("Yes") {
                        if let score = selectedScore {
                            gameStatus.score += score
                        }
                        selectedScore = nil // 关闭弹窗后重置状态
                    }
                    Button("No") {
                        if let score = selectedScore {
                            gameStatus.score -= score
                        }
                        selectedScore = nil
                    }
                }
            }
            .padding()
        }
    }
}
关键修改点
  • 替换showingAlert为selectedScore: Int?,通过存储具体分值关联按钮与弹窗逻辑
  • 每个按钮点击时设置对应分值到selectedScore,而非简单切换布尔值
  • 仅保留一个.alert修饰符,通过selectedScore != nil判断弹窗显示状态,内部根据选中分值执行分数操作
  • 将@ObservedObject改为@StateObject,符合SwiftUI对本地创建的ObservableObject的生命周期管理规范

内容的提问来源于stack exchange,提问作者Griffin-Reding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 06:45:30