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

SwiftUI应用按钮逻辑问题:Submit按钮标签切换失效

SwiftUI Submit按钮标签切换逻辑修复

问题场景

我用SwiftUI开发的应用里,通过单个结构体从数组生成多个mainButton,还有一个Submit按钮。想要实现的逻辑是:

  • 当某个mainButton被选中(已实现颜色和尺寸变化),且Submit按钮被点击过一次后,Submit按钮的标签切换为向上箭头图标;
  • 直到用户点击另一个mainButton(该按钮完成颜色和尺寸变化),Submit按钮才恢复为“Submit”文本。

目前其他功能正常,但Submit按钮的标签切换逻辑失效。我是Swift/SwiftUI新手,希望用基础的条件判断和变量实现该逻辑,以下是简化版代码:

//
//  AddView.swift
//  WriteOn
//
//  Created by Maurizio Zappettini on 2/11/23.
//

import SwiftUI

struct AddView: View {
    
    @State private var typeofMessageGeneric: String = ""
    @State private var lastButtonTapped: String = ""
    @State private var buttonCount: Int = 0
    
    let buttonData = [
        (mainButtonText: "A", mainButtonValue: "a"),
        (mainButtonText: "B", mainButtonValue: "b"),
        (mainButtonText: "C", mainButtonValue: "c"),
        (mainButtonText: "D", mainButtonValue: "d"),
    ]
    
    
    
    var body: some View {
      
        ZStack {  // Using ZStack for background gradient
            Rectangle()
                .frame(
                    minWidth: 0,
                    maxWidth: .infinity,
                    minHeight: 0,
                    maxHeight: .infinity,
                    alignment: .topLeading)
                .foregroundColor(.clear)
                .background(LinearGradient(colors: [.blue, .purple], startPoint: .top, endPoint: .bottom))
            
            
            VStack {  //Master VStack
                
                
                VStack { //Headline
                    
                    
                    
                    Text("Test View")
                        .font(.headline)
                        .padding()
                    
                }
                
                
                GeometryReader { geometry in  // Debug alignment
                    VStack(alignment: .center) {  //TextBox
                        
                        
                        
                        Rectangle()
                         .fill(Color.cyan)
                         .cornerRadius(20)
                         .frame(width: geometry.size.width * 0.8, height: 250, alignment: .center)
                       
                        
                        
                         .overlay(
                                HStack(alignment: .top){
                                    VStack {
                                        Spacer()
                                    }
                                    ScrollView {
                                        VStack(alignment: .center) {
                                            
                                            Text("getResponsePlaceHolder")
                                                .foregroundColor(.black)
                                                .frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
                                                .layoutPriority(2)
                                        }
                                    }
                                    VStack{
                                        
                                        ShareLink(item: "nothing"){
                                            Image(systemName: "square.and.arrow.up")
                                            
                                                .resizable()
                                                .scaledToFit()
                                                .frame(width: 25, height: 25)
                                                .foregroundColor(.black)
                                            
                                        }
                                    }
                                    VStack{
                                        Spacer()
                                    }
                                    
                                }
                                    .frame(height: geometry.size.height * 0.6) // find way to make it refer to actual box and not whole screen
                    )
                        
                         .frame(maxWidth: .infinity, maxHeight: .infinity)
                                
                            } //Vstack Top
                    
            }  //Geo Reader
                Spacer(minLength: 50
                )
                
              
                    ScrollView{
                        VStack { //Buttons
                            
                            ForEach(buttonData, id: \.mainButtonValue) { data in
                                
                                mainButton(typeofMessageGeneric: self.$typeofMessageGeneric, lastButtonTapped: self.$lastButtonTapped, buttonCount: self.$buttonCount, mainButtonText: data.mainButtonText, mainButtonValue: data.mainButtonValue)
                                
                                
                            }
                        } //Button Vstack end
                    }
                
          
                
                VStack{  //Footer
                    
               
                    
                   submitButton()

                      
                }
              
                }
            
        }
    }
    
    func submitButton() -> some View {
        
        return Button(action: getResponse) {
            if self.typeofMessageGeneric == self.lastButtonTapped && self.buttonCount == 0 {
                Text("Submit")
                    .font(.system(size: 20))
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            } else {
                
                Image(systemName: "arrow.clockwise.circle")
                    .font(.system(size: 30))
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
            
            
        }
        
        
    }
        
        
        // Create main buttons
        
        struct mainButton: View {
            
            @Binding var typeofMessageGeneric: String // Bind the variable inside this struct with the same one inside the ContentView struct
            @Binding var lastButtonTapped: String // Not currently used -- implement later if needed
            @Binding var buttonCount:Int
            
            var mainButtonText:String
            var mainButtonValue:String
            
            
            var body: some View {
                Button(action: {
                    

                    self.typeofMessageGeneric =  mainButtonValue
                    self.lastButtonTapped = mainButtonValue
                    
                    buttonCount = 0
                    
                    if self.typeofMessageGeneric == mainButtonValue{
                        buttonCount = 1
                    } else {
                        buttonCount = 0
                    }
                    
                                        
                }) {
                    Text(mainButtonText)
                    Text(String(buttonCount)) // testing only
                }
                .font(.system(size: 20))
                .foregroundColor(.white)
                .padding()
                .background(self.mainButtonValue == self.typeofMessageGeneric ? Color.teal : Color.purple)
                
                .cornerRadius(10)
                .scaleEffect(self.mainButtonValue == self.typeofMessageGeneric ? 1.12 : 1)
                .animation(.easeOut, value: 2)
                
                
                
            }
        }
        
                    
        

    func getResponse() {
    }
    
}
    
    
    
    
    
    
     











struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}

问题分析与修复

你的逻辑失效核心是状态变量管理混乱:buttonCount和lastButtonTapped冗余且逻辑冲突,同时缺少专门记录Submit是否被点击的状态变量。下面是分步修复方案:

步骤1:新增核心状态变量

在AddView里添加一个@State变量,专门记录Submit按钮的点击状态:

@State private var isSubmitTapped = false

步骤2:简化mainButton的点击逻辑

移除冗余的buttonCount和lastButtonTapped,点击按钮时只需更新选中状态,并重置Submit的点击标记:

struct mainButton: View {
    @Binding var typeofMessageGeneric: String
    @Binding var isSubmitTapped: Bool // 绑定Submit状态,点击新按钮时重置
    
    var mainButtonText: String
    var mainButtonValue: String
    
    var body: some View {
        Button(action: {
            typeofMessageGeneric = mainButtonValue
            isSubmitTapped = false // 切换按钮时,让Submit恢复文本
        }) {
            Text(mainButtonText)
        }
        .font(.system(size: 20))
        .foregroundColor(.white)
        .padding()
        .background(mainButtonValue == typeofMessageGeneric ? Color.teal : Color.purple)
        .cornerRadius(10)
        .scaleEffect(mainButtonValue == typeofMessageGeneric ? 1.12 : 1)
        .animation(.easeOut, value: typeofMessageGeneric) // 绑定选中状态触发动画
    }
}

步骤3:修正Submit按钮的判断逻辑

用typeofMessageGeneric(当前选中的按钮)和isSubmitTapped(是否点击过Submit)作为判断条件,逻辑更清晰:

func submitButton() -> some View {
    Button(action: {
        isSubmitTapped = true // 点击Submit后标记状态
        getResponse()
    }) {
        // 没选中按钮 或 没点击过Submit → 显示文本
        if typeofMessageGeneric.isEmpty || !isSubmitTapped {
            Text("Submit")
                .font(.system(size: 20))
                .foregroundColor(.white)
                .padding()
                .background(Color.blue)
                .cornerRadius(10)
        } else {
            // 选中按钮且点击过Submit → 显示向上箭头
            Image(systemName: "arrow.up.circle")
                .font(.system(size: 30))
                .foregroundColor(.white)
                .padding()
                .background(Color.blue)
                .cornerRadius(10)
        }
    }
    .disabled(typeofMessageGeneric.isEmpty) // 可选:未选中按钮时禁用Submit
}

步骤4:更新mainButton的调用

把新增的isSubmitTapped绑定传入:

mainButton(typeofMessageGeneric: $typeofMessageGeneric, isSubmitTapped: $isSubmitTapped, mainButtonText: data.mainButtonText, mainButtonValue: data.mainButtonValue)

完整修正代码

import SwiftUI

struct AddView: View {
    @State private var typeofMessageGeneric: String = ""
    @State private var isSubmitTapped = false // 记录Submit是否被点击
    
    let buttonData = [
        (mainButtonText: "A", mainButtonValue: "a"),
        (mainButtonText: "B", mainButtonValue: "b"),
        (mainButtonText: "C", mainButtonValue: "c"),
        (mainButtonText: "D", mainButtonValue: "d"),
    ]
    
    var body: some View {
        ZStack {
            Rectangle()
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .foregroundColor(.clear)
                .background(LinearGradient(colors: [.blue, .purple], startPoint: .top, endPoint: .bottom))
            
            VStack {
                VStack {
                    Text("Test View")
                        .font(.headline)
                        .padding()
                }
                
                GeometryReader { geometry in
                    VStack(alignment: .center) {
                        Rectangle()
                            .fill(Color.cyan)
                            .cornerRadius(20)
                            .frame(width: geometry.size.width * 0.8, height: 250)
                            .overlay(
                                HStack(alignment: .top){
                                    Spacer()
                                    ScrollView {
                                        VStack(alignment: .center) {
                                            Text("getResponsePlaceHolder")
                                                .foregroundColor(.black)
                                                .frame(maxWidth: .infinity, alignment: .center)
                                                .layoutPriority(2)
                                        }
                                    }
                                    VStack{
                                        ShareLink(item: "nothing"){
                                            Image(systemName: "square.and.arrow.up")
                                                .resizable()
                                                .scaledToFit()
                                                .frame(width: 25, height: 25)
                                                .foregroundColor(.black)
                                        }
                                    }
                                    Spacer()
                                }
                                    .frame(height: geometry.size.height * 0.6)
                            )
                    }
                }
                
                Spacer(minLength: 50)
                
                ScrollView{
                    VStack {
                        ForEach(buttonData, id: \.mainButtonValue) { data in
                            mainButton(typeofMessageGeneric: $typeofMessageGeneric, isSubmitTapped: $isSubmitTapped, mainButtonText: data.mainButtonText, mainButtonValue: data.mainButtonValue)
                        }
                    }
                }
                
                VStack{
                    submitButton()
                }
            }
        }
    }
    
    func submitButton() -> some View {
        Button(action: {
            isSubmitTapped = true
            getResponse()
        }) {
            if typeofMessageGeneric.isEmpty || !isSubmitTapped {
                Text("Submit")
                    .font(.system(size: 20))
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            } else {
                Image(systemName: "arrow.up.circle")
                    .font(.system(size: 30))
                    .foregroundColor(.white)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
        .disabled(typeofMessageGeneric.isEmpty)
    }
    
    struct mainButton: View {
        @Binding var typeofMessageGeneric: String
        @Binding var isSubmitTapped: Bool
        
        var mainButtonText: String
        var mainButtonValue: String
        
        var body: some View {
            Button(action: {
                typeofMessageGeneric = mainButtonValue
                isSubmitTapped = false
            }) {
                Text(mainButtonText)
            }
            .font(.system(size: 20))
            .foregroundColor(.white)
            .padding()
            .background(mainButtonValue == typeofMessageGeneric ? Color.teal : Color.purple)
            .cornerRadius(10)
            .scaleEffect(mainButtonValue == typeofMessageGeneric ? 1.12 : 1)
            .animation(.easeOut, value: typeofMessageGeneric)
        }
    }
    
    func getResponse() {
        // 这里添加Submit后的业务逻辑
    }
}

struct AddView_Previews: PreviewProvider {
    static var previews: some View {
        AddView()
    }
}

逻辑说明

  1. 状态清晰化:用isSubmitTapped专门记录Submit的点击状态,避免多个变量混乱;
  2. 按钮切换逻辑:点击新的mainButton时,自动重置isSubmitTapped,让Submit恢复文本;
  3. Submit显示逻辑:
    • 未选中按钮或未点击Submit → 显示“Submit”文本;
    • 已选中按钮且点击过Submit → 显示向上箭头图标;
  4. 简化冗余代码:移除了无用的buttonCount和lastButtonTapped,减少状态维护成本。

内容的提问来源于stack exchange,提问作者mzo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 13:20:28