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

SwiftUI中如何在不同视图结构体间访问变量?

解决SwiftUI跨视图传递选中状态的问题

问题核心

你需要将SecondView中按钮的选中状态(如tShirt)传递到Output视图,以此控制文本显示。本质是跨视图的数据传递,原代码中Output视图无法直接访问SecondView的@State变量,因为它们属于不同的作用域。


分步解决方案

1. 优化按钮组件(可选但推荐)

将点击逻辑整合到SelectButton内部,让组件更独立,避免在父视图重复编写onTapGesture:

import SwiftUI

struct SelectButton: View {
    @Binding var isSelected: Bool
    let color: Color // 用let替代@State,因为不需要在组件内修改
    let text: String // 同理用let
    
    var body: some View {
        ZStack {
            Capsule()
                .frame(height: 50)
                .foregroundColor(isSelected ? color : .gray)
            Text(text)
                .foregroundColor(.white)
        }
        .onTapGesture {
            isSelected.toggle() // 组件内部处理选中状态切换
        }
    }
}

struct SelectButton_Previews: PreviewProvider {
    static var previews: some View {
        SelectButton(isSelected: .constant(false), color: .green, text: "Option")
    }
}

2. 修正SecondView的语法错误并传递状态

原代码存在onTapGesture闭包未闭合、NavigationLink位置错误的问题,同时需要通过NavigationLink将选中状态传递给Output视图:

struct SecondView: View {
    @State private var tShirt = false
    @State private var jeans = false
    @State private var polo = false
    @State private var underpants = false
    
    var body: some View {
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.blue, .white]),
                           startPoint: .topLeading, endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 10) {
                Text("What are you washing today?")
                
                // T-Shirt按钮
                SelectButton(
                    isSelected: $tShirt,
                    color: .green,
                    text: "T-Shirt"
                )
                
                // 其他按钮同理(Jeans、Polo等)
                SelectButton(
                    isSelected: $jeans,
                    color: .blue,
                    text: "Jeans"
                )
                
                SelectButton(
                    isSelected: $polo,
                    color: .orange,
                    text: "Polo"
                )
                
                SelectButton(
                    isSelected: $underpants,
                    color: .purple,
                    text: "Underpants"
                )
                
                // 传递tShirt状态到Output视图
                NavigationLink(
                    destination: Output(isTShirtSelected: $tShirt),
                    label: {
                        Text("Next")
                            .foregroundColor(.black)
                    })
            }
            .padding()
        }
    }
}

struct SecondView_Previews: PreviewProvider {
    static var previews: some View {
        SecondView()
    }
}

3. 修改Output视图接收状态

在Output视图中添加@Binding属性接收SecondView传递的选中状态,然后根据状态控制文本显示:

struct Output: View {
    @Binding var isTShirtSelected: Bool // 接收从SecondView传递的状态
    
    var body: some View {
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.blue, .white]),
                           startPoint: .topLeading, endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
            
            VStack {
                Spacer().frame(height: 40.0)
                
                Text("Best Washing Option For You!")
                    .font(.system(size: 25, weight: .medium))
                    .foregroundColor(.white)
                    .padding(.bottom, 50.0)
                
                VStack{
                    HStack {
                        Text("Degrees")
                            .font(.system(size: 25, weight: .medium))
                            .foregroundColor(.white)
                            .padding(.trailing, 200.0)
                    }
                    
                    // 根据传递的状态判断是否显示文本
                    if isTShirtSelected {
                        Text("James")
                            .font(.title)     
                        
                        Spacer().frame(height: 150.0)
                        
                        HStack {
                            Text("Laundry detergent")
                                .font(.system(size: 25, weight: .medium))
                                .foregroundColor(.white)
                                .padding(.trailing, 80.0)
                        }
                    }
                    Spacer()
                }
            }
        }
    }
}

struct Output_Previews: PreviewProvider {
    static var previews: some View {
        Output(isTShirtSelected: .constant(true))
    }
}

进阶优化(多选项场景)

如果后续需要支持多个选项的状态传递,建议用枚举+集合管理选中状态,避免定义大量独立的@State变量:

  1. 定义衣物枚举:
enum LaundryItem: String, CaseIterable {
    case tShirt = "T-Shirt"
    case jeans = "Jeans"
    case polo = "Polo"
    case underpants = "Underpants"
}
  1. 修改SecondView用集合管理选中项:
struct SecondView: View {
    @State private var selectedItems = Set<LaundryItem>()
    
    var body: some View {
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.blue, .white]),
                           startPoint: .topLeading, endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
            
            VStack(spacing: 10) {
                Text("What are you washing today?")
                
                // 遍历所有衣物选项生成按钮
                ForEach(LaundryItem.allCases, id: \.self) { item in
                    // 自定义Binding关联集合的选中状态
                    let binding = Binding(
                        get: { selectedItems.contains(item) },
                        set: { isSelected in
                            if isSelected {
                                selectedItems.insert(item)
                            } else {
                                selectedItems.remove(item)
                            }
                        }
                    )
                    
                    SelectButton(
                        isSelected: binding,
                        color: .green,
                        text: item.rawValue
                    )
                }
                
                NavigationLink(
                    destination: Output(selectedItems: $selectedItems),
                    label: {
                        Text("Next")
                            .foregroundColor(.black)
                    })
            }
            .padding()
        }
    }
}
  1. 修改Output视图接收集合状态:
struct Output: View {
    @Binding var selectedItems: Set<LaundryItem>
    
    var body: some View {
        ZStack {
            LinearGradient(gradient: Gradient(colors: [.blue, .white]),
                           startPoint: .topLeading, endPoint: .bottomTrailing)
                .edgesIgnoringSafeArea(.all)
            
            VStack {
                Spacer().frame(height: 40.0)
                
                Text("Best Washing Option For You!")
                    .font(.system(size: 25, weight: .medium))
                    .foregroundColor(.white)
                    .padding(.bottom, 50.0)
                
                VStack{
                    HStack {
                        Text("Degrees")
                            .font(.system(size: 25, weight: .medium))
                            .foregroundColor(.white)
                            .padding(.trailing, 200.0)
                    }
                    
                    if selectedItems.contains(.tShirt) {
                        Text("James")
                            .font(.title)     
                        
                        Spacer().frame(height: 150.0)
                        
                        HStack {
                            Text("Laundry detergent")
                                .font(.system(size: 25, weight: .medium))
                                .foregroundColor(.white)
                                .padding(.trailing, 80.0)
                        }
                    }
                    
                    if selectedItems.contains(.jeans) {
                        Text("Jeans对应的文本")
                            .font(.title)
                    }
                    
                    Spacer()
                }
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 00:37:03