如何从SwiftData中获取数据并在SwiftUI视图中展示用户信息
SwiftData 登录后展示用户信息解决方案
核心问题分析
- 当前
@Query获取的是所有data对象的数组,直接访问profile.username会报错,因为数组没有该属性 - 未区分当前登录用户,无法精准获取目标用户数据
- 类名
data不符合Swift命名规范(类名需首字母大写)
分步解决方案
1. 保存登录状态
用@AppStorage存储当前登录用户的标识(比如用户名),让所有视图能共享登录状态:
// 在登录/注册成功的视图中添加 @AppStorage("currentUsername") var currentUsername: String? // 登录成功后赋值 currentUsername = "用户注册的用户名"
2. 重构SwiftData模型类
修正命名并拆分职责(建议把用户信息和运动记录分成独立模型,避免职责混乱):
import Foundation import SwiftData // 用户账户模型 @Model class UserAccount: Identifiable { let username: String let email: String let password: String let userID: UUID = UUID() init(username: String, email: String, password: String) { self.username = username self.email = email self.password = password } } // 运动记录模型 @Model class ExerciseRecord: Identifiable { var excName: String var workName: String var numOfSets: Int var numOfReps: Int var day: String // 关联用户 var user: UserAccount? init(excName: String, workName: String, numOfSets: Int, numOfReps: Int, day: String) { self.excName = excName self.workName = workName self.numOfSets = numOfSets self.numOfReps = numOfReps self.day = day } }
3. 修改ProfileView获取当前用户数据
添加过滤条件,精准获取当前登录用户,并处理UI展示:
import SwiftUI import SwiftData struct ProfileView: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss @AppStorage("currentUsername") var currentUsername: String? // 过滤当前登录用户的查询 @Query(filter: #Predicate<UserAccount> { $0.username == currentUsername }) var currentUser: [UserAccount] var body: some View { VStack{ VStack{ ZStack{ Color.gray.ignoresSafeArea().frame(width: 400,height: 250) Image("logo") .resizable() .aspectRatio(contentMode: .fill) .frame(width: 180, height: 100) .padding() Image(systemName: "camera.circle") .font(.system(size: 30)) .foregroundColor(.blue) .offset(x:60, y:70) // 安全展示用户名 if let user = currentUser.first { Text(user.username) .font(.title) .bold() .offset(y: 120) } } } Spacer() List { if let user = currentUser.first { Section(header: Text("账户信息")) { HStack { Text("Email:") Spacer() Text(user.email) .font(.body) } .padding() HStack { Text("Username:") Spacer() Text(user.username) .font(.body) } .padding() } } Button(action: logout) { Text("Logout") .foregroundColor(.red) .font(.headline) .padding() .cornerRadius(10) } .listRowBackground(Color.white) } .listStyle(.plain) Spacer() } } func logout() { currentUsername = nil // 清除登录状态 dismiss() // 返回登录页 } } #Preview { do { let config = ModelConfiguration(isStoredInMemoryOnly: true) let container = try ModelContainer(for: UserAccount.self, ExerciseRecord.self, configurations: config) // 添加测试用户 let testUser = UserAccount(username: "testUser", email: "test@example.com", password: "123456") container.mainContext.insert(testUser) return ProfileView() .modelContainer(container) .environment(\.appStorage, .init(suiteName: "testSuite")) } catch { return Text("Failed to create preview: \(error.localizedDescription)") } }
4. 关键说明
- 用
#Predicate过滤@Query,只获取当前登录用户的数据 - 通过
currentUser.first安全获取单个用户对象(确保登录状态下数据库中存在该用户) - 登录时设置
currentUsername,登出时清空,实现状态同步
内容的提问来源于stack exchange,提问作者Modhi
相关产品推荐
相关产品推荐

