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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:53:14