SwiftUI中如何向NotificationsAPI ViewModel传入userId
解决方法
1. 重构 NotificationsAPI,支持传入 userId
修改ViewModel,通过初始化方法接收userId,并修正URL拼接逻辑(解决原代码中硬编码字符串userId的错误):
import Foundation import SwiftUI class NotificationsAPI: ObservableObject { @Published var notifications: [KXNotification] = [] let userId: String // 根据后端要求调整类型,比如Int如果用数字ID // 初始化时传入userId init(userId: String) { self.userId = userId } func fetch() { // 先校验userId非空 guard !userId.isEmpty else { print("User ID cannot be empty") return } // 用URLComponents安全构建请求URL(自动处理特殊字符编码) guard var components = URLComponents(string: "xxxxxx.php") else { print("Invalid base URL") return } components.queryItems = [URLQueryItem(name: "id", value: userId)] guard let url = components.url else { print("Failed to construct request URL") return } let task = URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, error == nil else { print("Request error: \(error?.localizedDescription ?? "Unknown error")") return } do { let notifications = try JSONDecoder().decode([KXNotification].self, from: data) DispatchQueue.main.async { self?.notifications = notifications } } catch { print("JSON decoding error: \(error)") } } task.resume() } }
2. 在 NotificationsView 中传入 userId 创建ViewModel
根据userId的来源,有两种常见实现方式:
方式一:从父视图传入userId
如果NotificationsView是由其他视图导航进入,可通过初始化参数接收userId:
import SwiftUI struct NotificationsView: View { @StateObject private var viewModel: NotificationsAPI // 从父视图接收userId init(userId: String) { self._viewModel = StateObject(wrappedValue: NotificationsAPI(userId: userId)) } var body: some View { VStack(alignment: .center, spacing: 16) { VStack(alignment: .leading, spacing: 8) { HStack(alignment: .bottom, spacing: 0) { Text("Notifications") .font(.poppins(size: 20, weight: .medium)) Spacer(minLength: 0) Text("View All") .font(.poppins(size: 15, weight: .medium)) .themeForegroundColor(\.gray2) .onTapNavigate(to: AllExercisesView()) } Text("Notifications: \(viewModel.notifications.count)") .font(.openSans(size: 12, weight: .regular)) } VStack(alignment: .center, spacing: 16) { ForEach(viewModel.notifications, id: \.self) { notification in LongCardView( image: .web(link: notification.notificationImage), title: notification.notificationTitle, subTitle: notification.notificationDate, icon: "i_icon" ) } } .onAppear { viewModel.fetch() } } } } // 父视图跳转示例 struct ParentView: View { let currentUserId = "12345" // 实际从用户登录状态获取 var body: some View { NavigationStack { NavigationLink(destination: NotificationsView(userId: currentUserId)) { Text("Go to Notifications") } } } }
方式二:从本地存储(如UserDefaults)获取userId
如果userId已在用户登录后保存到本地,可直接在NotificationsView初始化时读取:
import SwiftUI struct NotificationsView: View { @StateObject private var viewModel: NotificationsAPI init() { // 从UserDefaults读取userId,替换为你的存储键 let userId = UserDefaults.standard.string(forKey: "currentUserId") ?? "" self._viewModel = StateObject(wrappedValue: NotificationsAPI(userId: userId)) } // 视图body内容与之前一致 }
关键注意点
- URL拼接错误:原代码中直接写
"xxxxxx.php?id=userId"会把字符串userId作为参数传递,而非实际用户ID,必须用插值或URLComponents替换。 - 安全构建URL:使用
URLComponents处理参数能自动处理特殊字符的URL编码,避免请求失败。 - ViewModel初始化:使用
StateObject时,需通过_viewModel = StateObject(wrappedValue: ...)的方式在初始化方法中创建实例,不能直接赋值。
内容的提问来源于stack exchange,提问作者Kane Vincent
相关产品推荐
相关产品推荐

