Home > database >  How to use conditional statements inside ForEach in swiftUI
How to use conditional statements inside ForEach in swiftUI

Time:01-21

How can I use conditional statements inside ForEach in swiftUI or is it possible?

What is Expected

My expectation is showing the correct food Items according to the ID(foodItem), Since i'm able to get all the food items inside the model class

Use-Case

I'm using a ForEach inside a GridView to display show different food Items, I have all my food items inside my model, and am passing a variable "foodItem" so, that the grid view get to know what type of food I need to show

Current Issue

Since I have the id for food Item I'm using a conditional statement inside the forEach to show the correct foodItem, but the Xcode is giving me an error, 2 errors.

Code of what I have done

LazyVGrid(columns: columns, spacing: 20) {
                                ForEach(
                                    if(foodType == 1){
                                        model.foodItems
                                    }else if ( foodType == 2){
                                        model.drinkItems
                                    }
                                    else{
                                        model.dessers
                                    }
 id: \.self) { item in
                            VStack{
                                GridImageView(item.image)
                                Text(item.food)
                                
                                
                            }
                            
                        }
                    }
                    .padding(.horizontal)

My Model class

import Foundation

class Model: ObservableObject {
    let foodItems = [
        FoodItems(food: "Rice",
                  image: "ricee"),
        FoodItems(food: "Fish Curry",
                  image: "fishcurry"),
        FoodItems(food: "Fish Curry 2",
                  image: "Fish Curry 2"),
        FoodItems(food: "Egg Curry",
                  image: "eggcurry")
    ]

    let drinkItems = [
        DrinkItems(food: "Cola",
                   image: "cola"),
        DrinkItems(food: "Pepsi",
                   image: "pepsi"),
        DrinkItems(food: "Limca",
                   image: "limca"),
    ]

    let dessers = [
        Desserts(food: "strawberry",
                 image: "strawberry"),
        Desserts(food: "chocolate",
                 image: "chocolate"),
    ]
}

Thanks in advance

CodePudding user response:

You could use a different approach than trying to use conditional statements that do not work inside a ForEach.

Use a general model for your data (Food), and use a filter to select the type you want to display, such as in this example code:

struct ContentView: View {
    @StateObject var model = Model()
    @State var foodType = 1
    
    var body: some View {
        // for testing
        Button("Change type") {
            foodType = foodType   1
            if foodType > 3 { foodType = 1 }
        }.buttonStyle(.bordered)
        
        ForEach(model.foodItems.filter{$0.type == foodType}) { item in
            VStack{
                Text(item.food)
                // image....
            }
        }
    }
}

struct Food: Identifiable, Hashable {
    let id = UUID()
    var type: Int
    var food: String
    var image: String
}

class Model: ObservableObject {
    let foodItems = [
        Food(type: 1, food: "Rice", image: "ricee"),
        Food(type: 1, food: "Fish Curry", image: "fishcurry"),
        Food(type: 1, food: "Fish Curry 2", image: "Fish Curry 2"),
        Food(type: 1, food: "Egg Curry", image: "eggcurry"),
        Food(type: 2, food: "Cola", image: "cola"),
        Food(type: 2, food: "Pepsi", image: "pepsi"),
        Food(type: 2, food: "Limca", image: "limca"),
        Food(type: 3, food: "strawberry", image: "strawberry"),
        Food(type: 3, food: "chocolate", image: "chocolate")
    ]
}

Better still, use enum for the type.

CodePudding user response:

You can make use of a protocol here and use a an array containing items matching that protocol in your ForEach

Example protocol

protocol Food {
    var food: String { get }
    var image: String { get }
}

And then conform all your types to this protocol

struct FoodItems: Food {
    let food: String
    let image: String
}

and so on

Next we add a function in the model class that returns the correct kind of food given a type parameter

func food(type: Int) -> [Food] {
    switch type {
    case 1:
        return foodItems
    case 2:
        return drinkItems
    default:
        return dessers
    }
}

and then you call this function from your view

LazyVGrid(columns: columns, spacing: 20) {
    ForEach(model.food(type: foodType), id: \.food) { item in
        VStack {
            GridImageView(item.image)
            Text(item.food)
        }
    }
}
  • Related