SwiftUI视图间值丢失问题:选中用户信息无法正常显示
问题分析与解决方案:详情页无法获取用户数据
核心问题
你遇到的问题根源是**UserList和userInfo两个视图各自创建了独立的AdministratorManager实例**。@StateObject修饰的对象会在每个视图初始化时生成全新的实例,所以你在UserList中给administratorManager.infoUtente[2]赋值的是第一个实例,而userInfo里读取的是另一个未赋值的全新实例,自然返回空值。
修复方案
我们需要让两个视图共享同一个AdministratorManager实例,以下是两种常用实现方式:
方式一:通过环境对象(EnvironmentObject)传递
- 在App的入口视图(如根导航栈或App结构体)中初始化
AdministratorManager,并注入到环境中:
@main struct YourApp: App { @StateObject private var adminManager = AdministratorManager() var body: some Scene { WindowGroup { NavigationStack { UserList() } .environmentObject(adminManager) } } }
- 修改
UserList,移除自身的@StateObject声明,改用@EnvironmentObject接收共享实例:
struct UserList: View { @EnvironmentObject var administratorManager: AdministratorManager @State var ricerca = "" @State var isPresented: Bool = false // 剩余body代码保持不变 }
- 修改
userInfo,同样改用@EnvironmentObject接收共享实例:
struct userInfo: View { @EnvironmentObject var administratorManager: AdministratorManager var body: some View { // 剩余body代码保持不变 } }
方式二:直接将实例作为参数传递给详情页
这种方式更直接,无需依赖环境:
- 修改
userInfo,添加接收AdministratorManager的初始化参数:
struct userInfo: View { let administratorManager: AdministratorManager var body: some View { // 剩余body代码保持不变 } }
- 在
UserList弹出sheet时,将当前的administratorManager实例传入详情页:
.sheetWithDetents( isPresented: $isPresented, detents: [.medium(),.large()] ) { print("The sheet has been dismissed") } content: { Group { userInfo(administratorManager: administratorManager) } .font(.title) }
额外优化建议
避免使用数组下标(如infoUtente[2])存储用户数据,推荐直接传递整个User对象给详情页,代码更清晰且不易出错:
- 修改
userInfo,直接接收User对象:
struct userInfo: View { let user: User var body: some View { HStack { Text("Nome: \(user.name)") .padding(.horizontal, 5) Text("Cognome: \(user.surname)") .padding(.horizontal, 5) }.padding(1) Text("Numero: \(user.number)") .padding(.horizontal, 5) Button("print", action: { print(user.number) }).padding(1) } }
- 在
UserList中添加状态存储选中的用户,点击按钮时赋值并传递:
struct UserList: View { @StateObject var administratorManager = AdministratorManager() @State var ricerca = "" @State var isPresented: Bool = false @State var selectedUser: User? var body: some View { ScrollView(.vertical, showsIndicators: false) { ForEach(administratorManager.users.sorted(using: [ KeyPathComparator(\.surname, order: .forward) ])) { user in // 原有视图代码省略 Button { selectedUser = user isPresented.toggle() } label: { Text("Tap me!") .padding() .background(Color.white) .cornerRadius(20) }.padding(1) } // 原有视图代码省略 .sheetWithDetents( isPresented: $isPresented, detents: [.medium(),.large()] ) { print("The sheet has been dismissed") } content: { Group { if let user = selectedUser { userInfo(user: user) } } .font(.title) } } } }
内容的提问来源于stack exchange,提问作者mickele29
相关产品推荐
相关产品推荐

