I'm trying to show array values, which I get from API call. I'm making addToCart request in one view and need to show it's result in other view.
class Cart: ObservableObject {
@Published var data: ShoppingCartContent?
@Published var sections: [SectionContent] = []
private var subscriptions = Set<AnyCancellable>() }
extension Cart {
func addToCart(productId: Int, productQty: Int) {
guard let token = UserDefaults.standard.string(forKey: "token") else { return }
NetworkManager.addProductToCart(token: token, productId: productId, productQty: productQty)
.sink(
receiveCompletion: { completion in
switch completion {
case .finished:
print("finished")
case .failure(let error):
print("AddToCart error", error)
}
},
receiveValue: { value in
print("Success:", value.success)
print("Data:", value.data)
self.data = value.data
self.sections = value.data.sections
print("Sections:", self.sections)
})
.store(in: &subscriptions) }}
I'm getting data from API, save them in @Published var sections, but I can't show them in other view, print shows it's nil.
struct ShoppingView: View {
@EnvironmentObject var viewModel: Cart
var body: some View {
ScrollView {
VStack(alignment: .leading) {
HStack {
Text("Delivery:")
.foregroundColor(Color.textFieldGrayColor)
ForEach(viewModel.sections, id: \.self) { section in
ForEach(section.items, id: \.self) { product in
Text(product.product_name)
}
}
}
}.onAppear {
print("My cart arr:", cartViewModel.data?.sections)
}
}
}
P.S. ShoppingView - is one of the tabs, I added (environmentObject) in MainView
@EnvironmentObject var viewModel: Cart
ShoppingView().environmentObject(viewModel)
I also tried to access array with @ObservedObject var viewModel = Cart() but it's also shows empty array.
CodePudding user response:
I do not recommend using ShoppingView().environmentObject(Cart())
: this will create a new Cart
instance every time the view is called. You will finish by re-creating the contents of your variables each time.
What I propose is to replace this call in your original code:
@EnvironmentObject var viewModel: Cart
with:
@StateObject var viewModel = Cart()
This will create a StateObject in the MainView that will be passed to ShoppingView
through the environment. Depending on your needs, also let viewModel = Cart()
works.
CodePudding user response:
When you are going to inject the view model you have to create an instance
Replace
@EnvironmentObject var viewModel: Cart
ShoppingView().environmentObject(viewModel)
with
ShoppingView().environmentObject(Cart())
The @EnvironmentObject
property wrapper is only necessary if you inherit the object.