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

SwiftUI中EnvironmentObject与ObservableObject预览无法显示输入数据

SwiftUI EnvironmentObject 数据传递失效问题修复

问题描述

在SwiftUI应用中输入测试数据后,最后展示数据的UserDataTest视图无法显示任何输入内容,刚接触EnvironmentObject,需要解决数据传递失效的问题。

问题根源

  1. 多层NavigationStack嵌套:子视图重复添加NavigationStack,导致环境对象的传递链断裂
  2. 冗余的@State中转与手动传递:使用额外的@State变量存储输入,再通过onTapGesture赋值,时机不可靠;同时手动传递.environmentObject(userInfo)容易造成实例不一致
  3. 数据未完全同步:部分输入字段(如身份证号、邮箱)未赋值到UserInfo对象中

修复方案

1. 简化导航结构

只在根视图ContentView保留一个NavigationStack,所有子视图不再嵌套NavigationStack,确保环境对象能在导航栈中自动传递。

2. 直接绑定@Published属性

将TextField直接绑定到UserInfo的@Published属性,无需额外@State变量,减少数据同步环节。

3. 移除手动传递环境对象的代码

依赖根视图注入的UserInfo实例自动传递,避免重复创建或传递错误的对象实例。

4. 补全数据同步逻辑

确保所有输入字段都赋值到UserInfo对应的属性中。

修改后的完整代码

class UserInfo: ObservableObject{
    @Published var textFieldName: String = ""
    @Published var textFieldLastName: String = ""
    @Published var textFieldMail: String = ""
    @Published var textFieldPhone: String = ""
    @Published var textFieldId: String = ""
}

struct ContentView: View {
    // 在根视图创建并持有UserInfo实例
    @StateObject private var userInfo = UserInfo()
    
    var body: some View {
        NavigationStack {
            welcomeView()
                .environmentObject(userInfo)
        }
    }
}

struct welcomeView: View {
    var body: some View {
        ZStack {
            Color.black
                .ignoresSafeArea()
            
            VStack {
                Image("llama")
                    .resizable()
                    .frame(width: 150, height: 150)
                
                Spacer()
                
                HStack {
                    NavigationLink(destination: LogginView()) {
                        ZStack {
                            RoundedRectangle(cornerRadius: 40.0)
                                .fill(Color(.gray))
                            
                            Text("Loggin")
                                .foregroundColor(.black)
                                .fontWeight(.semibold)
                        }
                    }
                    
                    NavigationLink(destination: CreateAccountView()) {
                        ZStack {
                            RoundedRectangle(cornerRadius: 40.0)
                                .fill(Color(.gray))
                            Text("Crear Cuenta")
                                .foregroundColor(.black)
                                .fontWeight(.semibold)
                        }
                    }
                }
                .frame(maxHeight: 100)
                .padding(.bottom, 40)
            }
        }
    }
}

struct LogginView: View {
    var body: some View {
        VStack {
            Text("Loggin")
        }
    }
}

struct CreateAccountView: View {
    @EnvironmentObject private var userInfo: UserInfo
    
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            
            VStack {
                HStack {
                    Spacer().frame(width: 15)
                    Text("Comenzemos !")
                        .fontWeight(.bold)
                        .font(.system(size: 30))
                        .foregroundColor(.white)
                    Spacer()
                }
                
                Spacer().frame(height: 10)
                
                HStack {
                    Spacer().frame(width: 15)
                    Text("Escribe tu numero de telefono. Nosotros te enviaremos un codigo de confirmacion ahi.")
                        .foregroundStyle(Color(.gray))
                    Spacer()
                }
                
                Spacer().frame(height: 40)
                
                HStack {
                    ZStack{
                        RoundedRectangle(cornerRadius: 20)
                            .fill(Color(.white))
                            .opacity(0.12)
                            .frame(maxWidth: 100)
                            .frame(maxHeight: 60)
                        HStack {
                            Image("peru")
                                .resizable()
                                .frame(maxHeight: 30)
                                .frame(maxWidth: 30)
                            
                            Text("+51")
                                .foregroundColor(.white)
                        }
                    }
                    
                    Spacer().frame(width: 10)
                    
                    ZStack{
                        RoundedRectangle(cornerRadius: 20)
                            .fill(Color(.white))
                            .opacity(0.2)
                            .frame(maxWidth: 300)
                            .frame(maxHeight: 60)
                        HStack {
                            TextField("", text: $userInfo.textFieldPhone, prompt: Text("Numero de telefono").foregroundStyle(Color(red: 200/255, green: 200/255, blue: 200/255)))
                                .keyboardType(.numberPad)
                                .padding(.leading, 20)
                                .foregroundColor(.white)
                        }
                    }
                }
                .padding(.horizontal, 15)

                Spacer()
                
                NavigationLink(destination: userDataName()) {
                    ZStack{
                        RoundedRectangle(cornerRadius: 45)
                            .foregroundStyle(Color(red: 76/255, green: 0/255, blue: 153/255))
                            .opacity(0.7)
                            .frame(maxHeight: 60)
                        
                        Text("Continue")
                            .foregroundStyle(Color(.gray))
                            .fontWeight(.semibold)
                    }
                }
            }
        }
    }
}

struct userDataName: View{
    @EnvironmentObject private var userInfo: UserInfo
    
    var body: some View{
        ZStack {
            Color(.black)
                .ignoresSafeArea()
            VStack{
                ZStack{
                    RoundedRectangle(cornerRadius: 20)
                        .fill(Color(.white))
                        .opacity(0.12)
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: 60)
                    
                    TextField("", text: $userInfo.textFieldName, prompt: Text("Nombre").foregroundStyle(Color(red: 200/255, green: 200/255, blue: 200/255)))
                        .padding(.leading, 15)
                        .foregroundColor(.white)
                }
                .padding(.horizontal, 15)
                .padding(.bottom, 20)
                
                ZStack{
                    RoundedRectangle(cornerRadius: 20)
                        .fill(Color(.white))
                        .opacity(0.12)
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: 60)
                    
                    TextField("", text: $userInfo.textFieldLastName, prompt: Text("Apellido").foregroundStyle(Color(red: 200/255, green: 200/255, blue: 200/255)))
                        .padding(.leading, 15)
                        .foregroundColor(.white)
                }
                .padding(.horizontal, 15)
                .padding(.bottom, 20)
                
                ZStack{
                    RoundedRectangle(cornerRadius: 20)
                        .fill(Color(.white))
                        .opacity(0.12)
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: 60)
                    
                    TextField("", text: $userInfo.textFieldId, prompt: Text("Documento de identidad").foregroundStyle(Color(red: 200/255, green: 200/255, blue: 200/255)))
                        .padding(.leading, 15)
                        .foregroundColor(.white)
                }
                .padding(.horizontal, 15)
                
                Spacer()
                
                NavigationLink(destination: emailData()) {
                    ZStack{
                        RoundedRectangle(cornerRadius: 45)
                            .foregroundStyle(Color(red: 76/255, green: 0/255, blue: 153/255))
                            .opacity(0.7)
                            .frame(maxHeight: 60)
                        
                        Text("Continue")
                            .foregroundStyle(Color(.gray))
                            .fontWeight(.semibold)
                    }
                }
            }
        }
    }
}

struct emailData: View{
    @EnvironmentObject private var userInfo: UserInfo
    
    var body: some View{
        ZStack {
            Color.black.ignoresSafeArea()
            
            VStack{
                HStack {
                    Spacer().frame(width: 15)
                    Text("Correo Electronico")
                        .font(.system(size: 30))
                        .fontWeight(.bold)
                        .foregroundColor(.white)
                    Spacer()
                }
                Spacer().frame(height: 10)
                
                HStack {
                    Spacer().frame(width: 15)
                    Text("Escribe tu correo electronico para asociarlo a tu cuenta ")
                        .foregroundStyle(Color(.gray))
                    Spacer()
                }
                
                Spacer().frame(height: 50)
                
                ZStack{
                    RoundedRectangle(cornerRadius: 20)
                        .fill(Color(.white))
                        .opacity(0.2)
                        .frame(maxWidth: .infinity)
                        .frame(maxHeight: 60)
                    
                    TextField("", text: $userInfo.textFieldMail, prompt: Text("Correo electronico").foregroundStyle(Color(red: 200/255, green: 200/255, blue: 200/255)))
                        .keyboardType(.emailAddress)
                        .padding(.leading, 30)
                        .foregroundColor(.white)
                }
                .padding(.horizontal, 15)
                
                Spacer()
                
                NavigationLink(destination: UserDataTest()) {
                    ZStack{
                        RoundedRectangle(cornerRadius: 45)
                            .foregroundStyle(Color(red: 76/255, green: 0/255, blue: 153/255))
                            .opacity(0.7)
                            .frame(maxHeight: 60)
                        
                        Text("Continue")
                            .foregroundStyle(Color(.gray))
                            .fontWeight(.semibold)
                    }
                }
            }
        }
    }
}

struct UserDataTest: View {
    @EnvironmentObject private var userInfo: UserInfo
    
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            
            VStack(spacing: 20) {
                Text(userInfo.textFieldName)
                    .foregroundStyle(Color(.red))
                    .font(.title)
                Text(userInfo.textFieldLastName)
                    .foregroundStyle(Color(.red))
                    .font(.title)
                Text(userInfo.textFieldMail)
                    .foregroundStyle(Color(.red))
                    .font(.title)
                Text(userInfo.textFieldPhone)
                    .foregroundStyle(Color(.white))
                    .font(.title)
                Text(userInfo.textFieldId)
                    .foregroundStyle(Color(.white))
                    .font(.title)
            }
        }
    }
}

额外优化说明

  • 使用@StateObject在根视图创建UserInfo实例,确保其生命周期与视图一致
  • 修复了邮箱输入框的键盘类型为.emailAddress,更符合输入场景
  • 统一了文本颜色,提升深色模式下的可读性
  • 调整了布局间距,优化视觉体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 21:02:00