fernando_gdv
fernando_gdv

Reputation: 11

Multiple Selection Navigation View List

If you look at my previous post you may understand the context. In this Swift file is a view in which the user is presented with several Exercises that come from a SQLite database. These exercises are presented in a Navigation View. The user should be able to select a day of the week using the picker, and then select multiple exercises that they wanna plan for that day. After they've done that for however many days they want, they click the save button which will save the Exercises they chose along with their respective days. These will then be displayed in another view, which is the one I wrote about in my previous post. This is the code:

import SwiftUI
import SQLite3

struct NewRoutine: View 
{
    @Binding var days: [String]
    @State var routineDay = "" // Initialize inside body
    @ObservedObject var exercisesdatabase: ExercisesDatabase
    @ObservedObject var routinedatabase: RoutineDatabase
    @State private var multiSelection = Set<UUID>() // Define multiSelection
    @Binding var slctInfo : Int

    var body: some View 
    {
        ZStack 
        {
            Rectangle()
                .foregroundColor(Color(.clear))
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .edgesIgnoringSafeArea(.all)
            Rectangle()
                .frame(width: 380, height: 550, alignment: .center)
                .foregroundColor(Color("Orange"))
                .cornerRadius(15)
                .shadow(radius: 15)

            VStack 
            {
                HStack 
                {
                    Button(action: {
                        slctInfo = 0
                    }) 
                    {
                        Image(systemName: "arrowshape.backward.fill")
                            .resizable().frame(width: 15, height: 17, alignment: .center)
                            .foregroundColor(Color.white)
                    }
                    .offset(x: -50, y: 5)

                    Text("Exercises")
                        .foregroundColor(.white)
                        .font(.title)
                        .fontWeight(.bold)
                        .padding(.bottom, 10)
                        .offset(y: 10)
                }

            NavigationView
                {
                    List 
                    {
                        ForEach(exercisesdatabase.exerciseList) { exercise in
                            ExerciseRow(exercise: exercise, isSelected: multiSelection.contains(exercise.id)) // Use custom row view with isSelected
                        }
                    }
                    .listStyle(.multipleSelection) // Enable multi-selection here
                }

            Picker(selection: $routineDay, label: Text("Day of the Week"))
                {
                    ForEach(days, id: \.self) 
                    {
                        i in Text(i)
                    }
                }
                .pickerStyle(.menu)

            Button(action: {
                for exercise in exercisesdatabase.exerciseList where multiSelection.contains(exercise.id) {
                    routinedatabase.routineList.append(Routines(routineID: routinedatabase.routineIDMax + 1, Exercise: exercise.Name, Day: routineDay))

            // Database interaction
                    var stmt: OpaquePointer?
                    let insertRoutine = "INSERT INTO Routines (RoutineID, Exercise, Day) VALUES (?, ?, ?)"

                    if sqlite3_prepare_v2(db, insertRoutine, -1, &stmt, nil) == SQLITE_OK 
                    {
                        let id = Int32(routinedatabase.routineIDMax + 1)
                        let exercise_db = exercise.Name
                        let day_db = routineDay

                        sqlite3_bind_int(stmt, 1, id)
                        sqlite3_bind_text(stmt, 2, (exercise_db as NSString).utf8String, -1, nil)
                        sqlite3_bind_text(stmt, 3, (day_db as NSString).utf8String, -1, nil)

                        if sqlite3_step(stmt) == SQLITE_DONE 
                        {
                            print("Routine saved successfully!")
                        } 
                        else
                        {
                            print("Error saving routine: \(String(cString: sqlite3_errmsg(db)))")
                        }
                    } 
                    else
                    {
                        print("Error preparing insert statement: \(String(cString: sqlite3_errmsg(db)))")
                    }

                    sqlite3_finalize(stmt)
                }
            }) 
                {
                ZStack
                {
                    Rectangle()
                        .frame(width: 100, height:50)
                        .foregroundColor(Color("Red"))
                        .cornerRadius(15)
                        .shadow(radius: 15)
                    Text("Save")
                        .foregroundColor(.white)
                        .bold()
                }
                }
                .offset(y: -10)
            }
        }
    }
}

struct ExerciseRow: View 
{
    let exercise: Exercises
    let isSelected: Bool

    var body: some View 
    {m
        HStack 
        {
            Text(exercise.Name)
            Spacer()
            
            if isSelected 
            {
                Image(systemName: "checkmark")
            }
        }
    }
}

The problem is that I am receiving the error "Type 'ListStyle' has no member 'multipleSelection'" at the line .listStyle(.multipleSelection).

Upvotes: 0

Views: 94

Answers (1)

Try this approach using List with selection (instead of the ForEach), such as in this example code:

struct Exercise: Identifiable {
    let id = UUID()  // <--- here
    let name: String
}

struct ContentView: View {
    let exercises = [Exercise(name: "Aerobics"),Exercise(name: "Jogging"),Exercise(name: "Swimming")]
    
    @State private var multiSelection = Set<UUID>()  // <--- here
    
    var body: some View {
        VStack {
            Text("\(multiSelection.count) selections")
            Spacer()
            List(exercises, selection: $multiSelection) { exercise in  // <--- here
                Text(exercise.name)
            }
        }
    }
}

Note, your comment .listStyle(.multipleSelection) // Enable multi-selection here is not correct. Multi-selection is not enable in .listStyle

Upvotes: 0

Related Questions