简体   繁体   中英

SwiftUI MVVM how to loop through data and store them inside array

I am using MVVM in my SwiftUI project and after I request to fetch data from the API, I want to loop through the data and store some of them inside an array, however it returns error, what is the correct method to do this?

Here is my code and data struct

MenuDetailView

struct MenuDetailView: View {
    @ObservedObject var viewModel = MenuDetailViewModel()
    
    var body: some View {
        ForEach(self.viewModel.variantGroup, id: \.self) { vg in
                /*** I Need to loop and store vg.variantGroupName into array viewModel.variantChosen, how? ***/

                self.viewModel.variantChosen.append(vg.VariantGroupName)
                // This always return error:
                // Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols

                VStack {
                    HStack {
                        Text(vg.variantGroupName)
                        Text(String(self.viewModel.arrVariantChoosen[0]))
                    }
                    VStack {
                        ForEach(vg.variant, id: \.self) { v in
                            Text(v.variantName)
                        }
                    }
                }
                
            }
        }
    }
}

MenuDetailViewModel.swift

class MenuDetailViewModel: ObservableObject, MenuDetailService {
    var apiSession: APIService
    @Published var detaildata: MenuDetailData?
    @Published var variantGroup = [MenuDetailVariantGroup]()
    @Published var variantChosen: Array<String> = []
    
    var cancellables = Set<AnyCancellable>()
    
    init(apiSession: APIService = APISession()) {
        self.apiSession = apiSession
    }
    
    func getMenuDetail() {
        let cancellable = self.getMenuDetail()
            .sink(receiveCompletion: { result in
                switch result {
                case .failure(let error):
                    print("Handle error: \(error)")
                case .finished:
                    break
                }
                
            }) { (detail) in
                self.detaildata = detail.data
                self.variantGroup = detail.data.variantGroup
        }
        cancellables.insert(cancellable)
    }
    
}

MenuDetailData.swift

struct MenuDetailData: Codable, Identifiable {
    let id = UUID()
    let idMenu: String
    let menuName: String
    let variantGroup: [MenuDetailVariantGroup]
}

MenuDetailVariantGroup.swift

struct MenuDetailVariantGroup: Codable, Identifiable, Hashable {
    let id = UUID()
    let variantGroupName: String
    let variant: [MenuDetailVariant]
    let limit: Int
}

MenuDetailVariant.swift

struct MenuDetailVariant: Codable, Identifiable, Hashable {
    let id = UUID()
    let variantName: String
}

Thank you all in advance

You can not add this inside the ForEach . In SwiftUI, ForEach is a view. It accepts view data, it's not the same as Array.forEach . You need to do it inside the view model. Like this

func getMenuDetail() {
        let cancellable = self.getMenuDetail()
            .sink(receiveCompletion: { result in
                switch result {
                case .failure(let error):
                    print("Handle error: \(error)")
                case .finished:
                    break
                }
                
            }) { (detail) in
                self.detaildata = detail.data
                self.variantGroup = detail.data.variantGroup
                self.variantChosen = self.variantGroup.map{$0.variantGroupName} //<--here
        }
        cancellables.insert(cancellable)
    }

Remove this from ForEach

 self.viewModel.variantChosen.append(vg.VariantGroupName)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM