SwiftUI中init内带参函数在onAppear时未更新的问题
解决SwiftUI中ObservableObject函数未使用正确参数更新的问题
问题根源
- ObservableObject错误使用
@State:@State仅适用于SwiftUI视图结构体,ObservableObject内的状态应使用普通变量或@Published(需监听变化时)。 @ObservedObject导致实例重复创建:视图重建时@ObservedObject会重新初始化对象,可能使onAppear的调用失效。- 初始空值无效调用:init中传入空字符串调用
grabItems属于无效请求,还可能干扰后续正确调用。 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
相关产品推荐
相关产品推荐

