EN VI

If inside ForEach, SwiftUI 5?

2024-03-12 09:00:08
How to If inside ForEach, SwiftUI 5

I have several exercises inside a database that the user has been able to add to a new table called routineList. This table contains the Exercise ID (Exercise) that corresponds to the ID of the exercise inside the exercise table (ExerciseID), and a day of the week (Day). The user can select a day of the week, and append several exercises from each day to routineList to build a workout routine. I want to display the exercises they have chosen, arranged by the day they belong to with the day as a title. This is what I have so far:

import SwiftUI
import SQLite3

struct YourRoutines: View 
{
    @State var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    
    @ObservedObject var routinedatabase: RoutineDatabase
    @ObservedObject var exercisedatabase: ExercisesDatabase
    
    var body: some View
    {
        var routines = routinedatabase.routineList
        
        ZStack
        {
            Rectangle()
                .foregroundColor(Color(.clear))
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .edgesIgnoringSafeArea(.all)
            Rectangle()
                .frame(width: 380, height: 600, alignment: .center)
                .foregroundColor(Color("Orange"))
                .cornerRadius(15)
                .shadow(radius: 15)
            
            VStack
            {
                Text("Your Routine")
                    .foregroundColor(.white)
                    .font(.title)
                    .fontWeight(.bold)
                    .padding(.bottom, 10)
                
                ForEach($days, id: \.self)
                { day in
                    VStack
                    {
                        Text(day.wrappedValue)
                            .font(.headline)
                            .padding(.bottom, 5)
                        
                        ForEach(routinedatabase.routineList) { routine in
                            if days.contains(routine.Day)
                            {
                                Text(routine.Name)
                            }
                        }
                    }
                    .padding(.horizontal)
                }
                .padding()
                .background(Color("Orange"))
                .cornerRadius(15)
            }
            .navigationTitle("Your Routines")
        }
    }
}

However, I keep getting these three errors. At the line: ForEach(routinedatabase.routineList) { routine in I get the following errors:

  1. Cannot convert value of type '[Routines]' to expected argument type 'Binding'
  2. Generic parameter 'C' could not be inferred

And at the line if days.contains(routine.Day) I receive this error:

  1. Instance method 'contains' requires the types 'String' and 'Binding<Subject.Element>' be equivalent.

I've tried using the id inside the inner ForEach loop but that didn't work.

Solution:

Try this example code, fixing some minor code issues, compiles for me.

struct YourRoutines: View {
    @State private var days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    
    @ObservedObject var routinedatabase: RoutineDatabase
    @ObservedObject var exercisedatabase: ExercisesDatabase
    
    var body: some View {
       // <--- here, no var declaration inside the view body
        
        ZStack {
            Rectangle()
                .foregroundColor(Color.clear)  // <--- here
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .edgesIgnoringSafeArea(.all)
            
            Rectangle()
                .frame(width: 380, height: 600, alignment: .center)
                .background(Color.orange) // <-- for testing
                .cornerRadius(15)
                .shadow(radius: 15)
            
            VStack {
                Text("Your Routine")
                    .foregroundColor(.white)
                    .font(.title)
                    .fontWeight(.bold)
                    .padding(.bottom, 10)
                
                ForEach(days, id: \.self) { day in   // <--- here, no $
                    VStack  {
                        Text(day)  // <--- here
                            .font(.headline)
                            .padding(.bottom, 5)
                        
                        ForEach(routinedatabase.routineList) { routine in
                            if days.contains(routine.Day)  {
                                  Text(routine.Name)
                            }
                        }
                    }
                    .padding(.horizontal)
                }
                
                .padding()
                .background(Color.orange) // <-- for testing
                .cornerRadius(15)
            }
            .navigationTitle("Your Routines")
        }
    }
}

// for my testing
struct Routine: Codable, Identifiable {
    let id: Int
    var Name: String  // <--- should be lower case
    var Day: String   // <--- should be lower case
}
// for my testing
class RoutineDatabase: ObservableObject {
    @Published var routineList = [Routine]()
}
// for my testing
class ExercisesDatabase: ObservableObject {
    @Published var items = [String]()
}
Answer

Login


Forgot Your Password?

Create Account


Lost your password? Please enter your email address. You will receive a link to create a new password.

Reset Password

Back to login