swift init()中包含参数的函数未更新onAppear{}

icnyk63a  于 2023-02-07  发布在  Swift
关注(0)|答案(2)|浏览(84)

试图调用init()中的函数。我有一个函数,它接受我在初始化器中调用的参数。我首先将参数设置为空字符串,直到当它出现时,我将值传入另一个视图。
我的问题是函数在视图第一次出现时没有立即更新,我的目标是让函数在视图生成后立即运行,并让视图立即更新(在视图中显示来自函数的值)。
我的猜测是因为我在init()中传入了初始的空字符串,所以我的函数没有使用更新后的变量触发。我不想将@State设置为@Binding,因为我不想每次调用observedObject时都必须传入一个值。任何建议都非常感谢。
总结一下我的问题,当我在视图第一次出现时调用grabItems方法时,它最初没有被正确的参数调用(它被一个空字符串调用)。

class testClass: ObservableObject {
    @State var uidNonUser: String
    @Published var itemsNonUser = [Item]() // items saved
    init(){
        self.uidNonUser = ""
        grabItems(userUID: uidNonUser) // << grabs things
    }
} 

struct testStruct: View {
  @ObservedObject var rm = testClass()
  @State var userUID: String // << variable passing to grabItems

 var body: some View {
 Text(rm.itemsNonUser.count)
   .onAppear{
      rm.grabItems(userUID: userUID)
     }
  }
}

仅供参考-粘贴我的实际grabItems食谱下面只是作为参考,以防它有助于理解这个问题。

func grabItems(userUID: String){
       //grab user thats not current user
        
        FirebaseManager.shared.firestore
            .collection("users")
            .document(userUID) // << passed in from view
            .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
                    let recipe = RecipeItem(id: recipeID, recipeTitle:recipeTitle , recipePrepTime: recipePrepTime, recipeImage: recipeImage, createdAt: createdAt, recipeCaloriesMacro: recipeCaloriesMacro, recipeFatMacro: recipeFatMacro, recipeCarbMacro:recipeCarbMacro, recipeProteinMacro: recipeProteinMacro, directions: directions, ingredientItem: ingredients)

                    return recipe

                }
            }
        }
qqrboqgw

qqrboqgw1#

请尝试使用此示例代码在View首次出现时更新它。

// for testing
struct RecipeItem {
    var recipeTitle: String
    // ...
}

class TestClass: ObservableObject {
    @Published var itemsNonUser = [RecipeItem]()  // <-- here
    
    func grabItems(userUID: String){
        //...
        // for testing
        itemsNonUser = [RecipeItem(recipeTitle: "banana cake with ID: \(userUID)")]
    }
    
}

struct TestStruct: View {
    @StateObject var rm = TestClass()  // <-- here
    @State var userUID: String
    
    var body: some View {
        VStack {
            Text(rm.itemsNonUser.first?.recipeTitle ?? "no name")
            Text("count: \(rm.itemsNonUser.count)")  // <-- here
        }
        .onAppear{
            rm.grabItems(userUID: userUID) // <-- here
        }
    }
}

struct ContentView: View {
    let userUID = "123456"
    var body: some View {
        TestStruct(userUID: userUID) // <-- here
    }
}
disbfnqx

disbfnqx2#

在我的示例中(可能是针对我的特定情况的),我更新了grabItems方法以返回一个Int,因为我的视图试图显示计数。
然后我就像这样直接在视图中调用它,它就工作了:

Text(String(rm.grabItems(userUID: userUID))).bold() // << calling function directly in view

相关问题