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

SwiftUI中init内带参函数在onAppear时未更新的问题

解决SwiftUI中ObservableObject函数未使用正确参数更新的问题

问题根源

  1. ObservableObject错误使用@State:@State仅适用于SwiftUI视图结构体,ObservableObject内的状态应使用普通变量或@Published(需监听变化时)。
  2. @ObservedObject导致实例重复创建:视图重建时@ObservedObject会重新初始化对象,可能使onAppear的调用失效。
  3. 初始空值无效调用:init中传入空字符串调用grabItems属于无效请求,还可能干扰后续正确调用。
  4. userUID未初始化:@State变量必须有初始值,否则onAppear触发时可能仍为空。

修正后的代码

1. 修正ObservableObject类

class TestClass: ObservableObject {
    var uidNonUser: String = "" // 改为普通变量,需监听变化可添加@Published
    @Published var itemsNonUser = [RecipeItem]() // 统一类型为RecipeItem

    // 移除init中的无效grabItems调用
    init() {}

    func grabItems(userUID: String){
        self.uidNonUser = userUID // 可选:保存传入的UID
        FirebaseManager.shared.firestore
            .collection("users")
            .document(userUID)
            .collection("userRecipes")
            .addSnapshotListener { (snapshot, err) in
                guard let documents = snapshot?.documents else{
                    print("no documents present")
                    return
                }

                self.itemsNonUser = documents.map { querySnapshot -> RecipeItem in
                    let data = querySnapshot.data()
                    let recipeTitle = data["recipeTitle"] as? String ?? ""
                    let recipePrepTime = data["recipePrepTime"] as? String ?? ""
                    let recipeImage = data["recipeImage"] as? String ?? ""
                    let createdAt = data["createdAt"] as? String ?? ""
                    let ingredients = data["ingredientItem"] as? [String: String] ?? ["": ""]
                    let directions = data["directions"] as? [String] ?? [""]
                    let recipeID = data["recipeID"] as? String ?? ""
                    let recipeCaloriesMacro = data["recipeCaloriesMacro"] as? Int ?? 0
                    let recipeFatMacro = data["recipeFatMacro"] as? Int ?? 0
                    let recipeCarbMacro = data["recipeCarbMacro"] as? Int ?? 0
                    let recipeProteinMacro = data["recipeProteinMacro"] as? Int ?? 0
                    return RecipeItem(
                        id: recipeID,
                        recipeTitle: recipeTitle,
                        recipePrepTime: recipePrepTime,
                        recipeImage: recipeImage,
                        createdAt: createdAt,
                        recipeCaloriesMacro: recipeCaloriesMacro,
                        recipeFatMacro: recipeFatMacro,
                        recipeCarbMacro: recipeCarbMacro,
                        recipeProteinMacro: recipeProteinMacro,
                        directions: directions,
                        ingredientItem: ingredients
                    )
                }
            }
    }
}

2. 修正视图结构体

struct TestStruct: View {
    @StateObject var rm = TestClass() // 改用@StateObject保证实例唯一
    @State var userUID: String = "" // 给@State变量添加初始值

    var body: some View {
        Text("\(rm.itemsNonUser.count)")
            .onAppear{
                // 空值检查,避免无效请求
                guard !userUID.isEmpty else {
                    print("userUID为空,无法发起请求")
                    return
                }
                rm.grabItems(userUID: userUID)
            }
    }
}

关键修正说明

  • 替换@State:ObservableObject中禁用@State,若需监听uidNonUser变化,添加@Published修饰符即可。
  • 改用@StateObject:保证ObservableObject实例在视图生命周期内唯一,避免视图重建时对象重置。
  • 移除无效初始化调用:仅在视图出现且有有效参数时调用grabItems,避免空请求。
  • 初始化userUID:@State变量必须有初始值,同时在onAppear中添加空值检查,确保传入正确参数。
  • 类型统一:确保itemsNonUser的类型与grabItems返回的RecipeItem一致,避免类型错误。

内容的提问来源于stack exchange,提问作者Swink

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:01:29