SwiftUI - Passing a variable to Observable Object

随声附和 提交于 2021-01-28 19:03:40

问题


I have a view that's receiving an ID value from the previous view. I need to also take that ID value and pass it into an ObservableObject so that I can run a Firestore query on that ID. I'm at a loss as to how to grab that ID for my ObservableObject.

struct ItemView: View {
   var itemName: String
   var itemID: String
   @ObservedObject var items = getItemsData()
   // ..... etc
   }


 class getItemsData() {
    @Published var data = [items]()
    init() {
       let db = Firestore.firestore()
       db.collection("items").whereField("itemID", isEqualTo: *THIS IS WHERE I NEED THE ITEMID *),addSnapshotListner {(snap, err) in ...
}

So in the query call, I need to call the ItemID value to query based on that value that's defined at the top of the view.


回答1:


I think your getItemsData class should inherit from ObservableObject

class GetItemsData: ObservableObject {...}

To get itemId into your GetItemsData instance, you can add a parameter to your init()

class GetItemsData: ObservableObject {
    init(itemId: String) {
        ...
    }
}

}

To tie it all together you have two choices. you could add an init to your ItemView like:

struct ItemView: View {
    let itemName: String
    let itemModel: GetItemsData
    init(itemName: String, itemID: String) {
        self.itemName = itemName
        itemModel = GetItemsData(itemId: itemID)
    }
}

I prefer instead to pass the observable object into the view, so it is more like a view model in MVVM

struct ItemView: View {
    let itemName: String
    let itemModel: GetItemsData



回答2:


if your ObservableObject has any state or is not located at top level view @tomcully way will end up with instantiating it with each parent view updating.

And also if you call an api inside init(), you will make many unnecessary api call.

You can do like this:

struct ItemView: View {
   var itemName: String
   var itemID: String
   @ObservedObject var items = getItemsData()
   var body: some View {
     ...
    .onAppear {
      items.setID(itemID)
    }
  }
}
class getItemsData: ObservedObject {
    let db = Firestore.firestore()
    @Published var data = [items]()
    var itemID: String = ""
    
    func setID(_ id: String) {
        if itemID != id {
            itemID = id
            db.collection("items").whereField("itemID", isEqualTo: itemID),addSnapshotListner {(snap, err) in ...
            }
        }
    }
}

Note: but even the above way, you cannot avoid instantiation of the ObservableObject with each parent view update, so if you don't want to it, you can use @StateObject(only ios 14 or above), or you can instantiate ObservableObject in different view and pass it as @environmentObject.



来源:https://stackoverflow.com/questions/60868330/swiftui-passing-a-variable-to-observable-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!