Home > Net >  How could I correctly implement favourites in SwiftUI?
How could I correctly implement favourites in SwiftUI?

Time:07-18

I am building an app that will store multiple Nintendo consoles and their details (kinda like Mactracker but for Nintendo stuff).

I wanna store consoles that the user chooses in a favourites category on the main menu but I can't implement it correctly.

I have the main menu which shows the different categories as well as the favourite category which is duplicated for each category:

enter image description here

Each favourites "button" takes me to the favourites of only a specific category (the category beneath it) and I would like that all of them are in only one tab and not in multiple tabs like they are so far.

The favourites category is a bool defined in the Console List which will be listed below.

Thanks for the help and sorry if its a stupid question, I'm quite new to programming.

Main Menu:

struct MainMenu: View {
    // Use categories ordered by alphabetical order
    var categories = ConsoleList.categories.sorted(by: {$0.key < $1.key})
    var body: some View {
        // Loop on categories
        NavigationView{
            List(categories, id:\.key){category in
                // The NavigationLink that takes me to the favorites view
                NavigationLink(destination: Favorites(con: category.value)){
                    Image(systemName: "heart")
                    Text("Favorites")
                        .fontWeight(.semibold)
                }
                NavigationLink(destination: ConsoleMenu(con: category.value), label:{
                    
                    Image(systemName: "folder")
                    
                        .foregroundColor(.red)
                        .scaledToFit()
                        .frame(height: 30)
                        .cornerRadius(4)
                        .padding(.vertical, 4)
                    VStack{
                        Text(category.key)
                            .fontWeight(.semibold)
                    }
                })
            }
            .navigationTitle("")
        }
    }
}

Favourites menu:

struct Favorites: View {
    
    var con: [ConsoleDetails]
    var body: some View {
        
        List(con){ cons in
            if cons.favorites {
                
                NavigationLink(destination: ConsoleDetailView(con: cons), label:{
                    Image(cons.imgName)
                        .resizable()
                        .scaledToFit()
                        .frame(height: 50)
                        .cornerRadius(4)
                        .padding(.vertical, 4)
                        .navigationTitle("\(cons.category)")
                    
                    VStack (alignment: .leading){
                        if cons.category == "Game & Watch" {
                            Text(cons.consoleName)
                                .fontWeight(.semibold)
                            Text(cons.mostSoldGame)
                                .font(.subheadline)
                        }else{
                            Text(cons.consoleName)
                                .fontWeight(.semibold)
                        }
                    }
                }).navigationTitle("Favorites")
            }
        }
    }
}

struct favorites_Previews: PreviewProvider {
    static var previews: some View {
        Favorites(con: ConsoleList.consoles)
    }
}

The consoles list:

struct ConsoleDetails: Identifiable{
    let id = UUID()
    var imgName: String = ""
    var consoleName: String = ""
    var mostSoldGame: String = ""
    var initialPrice: String = ""
    var ReleaseDate: String = ""
    var Discontinuation: String = ""
    var category: String = ""
    var estimatedPricedToday: String = ""
    var cables: String = ""
    var favorites: Bool
}



struct ConsoleList{
    //The consoles list has more consoles usually but I'll only put one to save space
    static var categories = Dictionary(grouping: consoles, by: {$0.category } )
    static var favs = Dictionary(grouping: consoles, by: {$0.favorites} )
    static var consoles = [
        //Current Consoles
        ConsoleDetails(imgName: "NS_OG",
                       consoleName: "Nintendo Switch",
                       mostSoldGame: "Mario Kart 8 Deluxe",
                       initialPrice: "299.99",
                       ReleaseDate: "Mar 3, 2017",
                       Discontinuation: "Still Available",
                       category: "Current Consoles",
                       estimatedPricedToday: "$200-250 used",
                       cables: "HDMI, USB Type-C",
                       favorites: true),

Edit: I have added what was proposed but I get an error in the nav link. See below:

List{
                Section {
                    // The NavigationLink that takes me to the favorites view
                    NavigationLink {
                        Favorites() // Right Here: Missing argument for parameter 'con' in call
                    } label: {
                        Image(systemName: "heart")
                        Text("Favorites")
                            .fontWeight(.semibold)
                    }
                }
                Section {
                    ForEach(categories, id: \.key){ category in
                        NavigationLink(destination: ConsoleMenu(con: category.value), label:{
                            Image(systemName: "folder")
                                .foregroundColor(.red)
                                .scaledToFit()
                                .frame(height: 30)
                                .cornerRadius(4)
                                .padding(.vertical, 4)
                            VStack{
                                Text(category.key)
                                    .fontWeight(.semibold)
                            }
                        })
                    }
                }
                
            }

CodePudding user response:

Instead of having the list loop over the categories, you could put a ForEach in the List.

Then, you could have one favorites link, and put it in a different section to differentiate it.

List {
    Section {
        NavigationLink {
            Favorites(con: /* (1) */ ConsoleList.consoles)
        } label: { /* ... */ }
    }

    Section {
        ForEach(categories, id: \.key) { category in
            // ...
        }
    }
}

(1) You will also need to pass in a list of all the consoles to show.

  • Related