1

My project is creating an ordering app, and in this screen about the menu detail, there are menu variants which users can choose / add-on, I need to iterate an array of [MenuDetailVariantGroup] and I need to get the index of the array, how do I do this? While in the for loop I also need to append a variable into a @Published var variantChosen, however if I do self.viewModel.variantChosen.append(1), it always returns an error. Below is my codes:

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
}

MenuDetailViewModel.swift

class MenuDetailViewModel: ObservableObject, MenuDetailService {
    var apiSession: APIService
    @Published var detaildata: MenuDetailData?
    @Published var variantGroup = [MenuDetailVariantGroup]()
    @Published var variantChosen: Array<Int> = []
    
    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)
    }
    
}

MenuDetailView

struct MenuDetailView: View {
    @ObservedObject var viewModel = MenuDetailViewModel()
    
    var body: some View {
        ForEach(self.viewModel.variantGroup, id: \.self) { vg in
                /*** I Need to get the index of each iteration here, how? ***/
                VStack {
                    HStack {
                        Text(vg.variantGroupName)
                        Text(String(self.viewModel.arrVariantChoosen[0]))
                    }
                    VStack {
                        ForEach(vg.variant, id: \.self) { v in
                            Text(v.variantName)
                        }
                    }
                }
                // I also need to append Int to @Published var variantChosen
                self.viewModel.variantChosen.append(1)
                // This always return error:
                // Type '()' cannot conform to 'View'; only struct/enum/class types can conform to protocols
            }
        }
    }
}

This is the codes that I have tried so far but failed and return empty

// This returns blank
ForEach(0..<self.viewModel.variantGroup.count) { i in
    Text("\(self.viewModel.variantGroup[i].variantGroupName)")
}

// This too returns blank
ForEach(self.viewModel.variantGroup.indices) { i in
    Text("\(self.viewModel.variantGroup[i].variantGroupName)")
}

Thank you all in advance

3
  • What you have tried should work fine, see this answer for instance. Maybe the array is empty? You have a method getMenuDetail in your view model but is it ever called? Commented Jan 12, 2021 at 12:24
  • It does get called, with the current "ForEach(self.viewModel.variantGroup, id: \.self) { vg in" returns the data, but I could not get the index, weirdly with the "ForEach(0..<self.viewModel.variantGroup.count) { i in" returns blank Commented Jan 12, 2021 at 12:26
  • Also why is that method calling itself? But maybe you should ignore that function for now and hardcode some values into the variantGroup array and see if you can get the ForEach to work, that way you deal with one problem at a time. Commented Jan 12, 2021 at 12:30

1 Answer 1

3

You can use enumerated to have both index and element, like

    var body: some View {
        ForEach(Array(self.viewModel.variantGroup.enumerated()), id: \.1) { index, vg in
                /*** I Need to get the index of each iteration here, how? ***/
                VStack {
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks you so much man, this does work, how do I append the value to the array in the ViewModel @Published var variantChosen in the foreach loop though?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.