NEW: My new book Pro SwiftUI is out now – level up your SwiftUI skills today! >>

SOLVED: Selected List

Forums > SwiftUI

Good morning all,

I am trying to create a selectable list much like the iTunes Store app when you tap Genres in the nav bar at the top a sheet comes up that shows a list of Genres to select from and a checkmark to the right on the selected row. I am just at a loss on how to get the checkmark on the row.

List(selection: $selectedTopicData) {
    ForEach(listOfTopics, id: \.self) { topic in
        HStack {
            Text(topic.name)
                .textViewModifier(for: .body, weight: .regular, color: .primary)
            Spacer()
        }
        .contentShape(Rectangle())
        .onTapGesture {
            selectedTopicData = topic
            let _ = print("TopicData: \(String(describing: selectedTopicData))")
            dismiss()
        }
    }
}

If anyone has any ideas on how to add a checkmark that would be great.

Thanks Taz

   

Hi, have you tried to add property to your topic var selected = false? Then in .onTapGesture you can switch it to be true. And as a result in your HStack you can check if that property is true and assign it a checkmark.

Something like that:

HStack {
            Text(topic.name)
                .textViewModifier(for: .body, weight: .regular, color: .primary)
            Spacer()
            if topic.selected {
              Image(systemName: "checkmark")
            }
        }

   

I assume you mean a Menu Do this little project.

enum of the genres (including All), Note that it CaseIterable

enum Genre: String, CaseIterable {
    case all, house, jazz, rock
}

A Mock struct

struct Music: Identifiable {
    let id = UUID()
    let title: String
    let artist: String
    let genre: Genre
}

and now for View

struct ContentView: View {
    // MOCK DATA
    let allMusic = [
        Music(title: "Song 1", artist: "Artist 1", genre: .house),
        Music(title: "Song 2", artist: "Artist 1", genre: .house),
        Music(title: "Song 3", artist: "Artist 1", genre: .jazz),
        Music(title: "Song 4", artist: "Artist 2", genre: .jazz),
        Music(title: "Song 5", artist: "Artist 2", genre: .jazz),
        Music(title: "Song 6", artist: "Artist 2", genre: .rock),
        Music(title: "Song 7", artist: "Artist 3", genre: .rock),
        Music(title: "Song 8", artist: "Artist 3", genre: .rock),
        Music(title: "Song 8", artist: "Artist 3", genre: .rock),
    ]

    // A property to store the selected Genre
    @State private var selectedGenre = Genre.all

    // A computed property to filter the selected genre
    var filteredMusic: [Music] {
        if selectedGenre != .all {
            return allMusic.filter { $0.genre == selectedGenre }
        }

        return allMusic
    }

    var body: some View {
        NavigationStack {
            List {
                ForEach(filteredMusic) { music in
                    HStack {
                        VStack {
                            Text(music.title)
                                .font(.headline)
                            Text(music.artist)
                                .foregroundStyle(.secondary)
                        }

                        Spacer()

                        Text(music.genre.rawValue.capitalized)
                    }
                }
            }
            .navigationTitle("Music Library")
            .toolbar { // tool bar in navigation bar with a picker to select genre
                ToolbarItem {
                    Menu {
                        Picker("Genre", selection: $selectedGenre) {
                            ForEach(Genre.allCases, id: \.self) {
                                Text($0.rawValue.capitalized)
                            }
                        }
                    } label: {
                        Label("Genre", systemImage: "ellipsis.circle")
                    }
                }
            }
        }
    }
}

   

@ygeras

Thanks so much for the reply. Sometimes the simplest solution is the hardest to figure out, LOL. At least for me, I tend to overthink the problem. So I did this using UserDefaults. I wanted a simple way to persist the choice if still on the tab. I ended up with this:

@AppStorage(StorageKeys.topicSelected.rawValue) var topicSelected = ""
List(selection: $selectedTopicData) {
    ForEach(listOfTopics, id: \.self) { topic in
        HStack {
            Text(topic.name)
                .textViewModifier(for: .body, weight: .regular, color: .primary)
            Spacer()
            if topic.name == topicSelected {
                Image(systemName: "checkmark")
                    .resizable()
                    .frame(width: 10, height: 10)
                    .foregroundColor(Color.accentColor)
                    .bold()
            }
        }
        .contentShape(Rectangle())
        .onTapGesture {
            selectedTopicData = topic
            topicSelected = topic.name
            dismiss()
        }
    }
}
.listStyle(.plain)

Anyway, thanks for your reply, Taz

   

@NigelGee

Hey, my friend, I appreciate the reply. I'd thought about doing it in a Menu which would give me the checkmark automatically, but my list of topics is over a 100. So I didn't feel the menu was the right fit for a list that long. Plus, by putting this in a sheet I can give the user the ability to filter the topics with .searchable modifier.

Again my friend, thanks for great solution.

Taz

   

Hacking with Swift is sponsored by Judo

SPONSORED Let’s face it, SwiftUI previews are limited, slow, and painful. Judo takes a different approach to building visually—think Interface Builder for SwiftUI. Build your interface in a completely visual canvas, then drag and drop into your Xcode project and wire up button clicks to custom code. Download the Mac App and start your free trial today!

Try now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.