SwiftUI中EnvironmentObject与ObservableObject预览无法显示输入数据
SwiftUI EnvironmentObject 数据传递失效问题修复
问题描述
在SwiftUI应用中输入测试数据后,最后展示数据的UserDataTest视图无法显示任何输入内容,刚接触EnvironmentObject,需要解决数据传递失效的问题。
问题根源
- 多层NavigationStack嵌套:子视图重复添加
NavigationStack,导致环境对象的传递链断裂 - 冗余的@State中转与手动传递:使用额外的
@State变量存储输入,再通过onTapGesture赋值,时机不可靠;同时手动传递.environmentObject(userInfo)容易造成实例不一致 - 数据未完全同步:部分输入字段(如身份证号、邮箱)未赋值到
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
相关产品推荐
相关产品推荐

