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

SwiftUI视图间值丢失问题:选中用户信息无法正常显示

问题分析与解决方案:详情页无法获取用户数据

核心问题

你遇到的问题根源是**UserList和userInfo两个视图各自创建了独立的AdministratorManager实例**。@StateObject修饰的对象会在每个视图初始化时生成全新的实例,所以你在UserList中给administratorManager.infoUtente[2]赋值的是第一个实例,而userInfo里读取的是另一个未赋值的全新实例,自然返回空值。

修复方案

我们需要让两个视图共享同一个AdministratorManager实例,以下是两种常用实现方式:

方式一:通过环境对象(EnvironmentObject)传递

  1. 在App的入口视图(如根导航栈或App结构体)中初始化AdministratorManager,并注入到环境中:
@main
struct YourApp: App {
    @StateObject private var adminManager = AdministratorManager()
    
    var body: some Scene {
        WindowGroup {
            NavigationStack {
                UserList()
            }
            .environmentObject(adminManager)
        }
    }
}
  1. 修改UserList,移除自身的@StateObject声明,改用@EnvironmentObject接收共享实例:
struct UserList: View {
    @EnvironmentObject var administratorManager: AdministratorManager
    @State var ricerca = ""
    @State var isPresented: Bool = false
    
    // 剩余body代码保持不变
}
  1. 修改userInfo,同样改用@EnvironmentObject接收共享实例:
struct userInfo: View {
    @EnvironmentObject var administratorManager: AdministratorManager
    
    var body: some View {
        // 剩余body代码保持不变
    }
}

方式二:直接将实例作为参数传递给详情页

这种方式更直接,无需依赖环境:

  1. 修改userInfo,添加接收AdministratorManager的初始化参数:
struct userInfo: View {
    let administratorManager: AdministratorManager
    
    var body: some View {
        // 剩余body代码保持不变
    }
}
  1. 在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对象给详情页,代码更清晰且不易出错:

  1. 修改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)
    }
}
  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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 19:48:22