Search code examples
swiftxcodeforeachswiftuiswiftui-navigationlink

Unnamed argument #2 must precede argument 'destination'


I am trying to make a list of eatery locations each of which are displayed in an EateryRow which is able to be clicked to move to the EateryDetail page, however with the implementation of this code I get an error which I believe is related to the syntax of the NavigationLink argument.

Also: I found this question which seems to have the same problem as me but it remains unanswered.

import SwiftUI

struct EateryList: View {
    @Binding var eateries: [Eatery]
    var body: some View {
        NavigationView {
            VStack {
                List {
                    ForEach(eateries) {
                        NavigationLink(destination: EateryDetail(eatery: $eateries[identifiedBy: $0])) { //error here
                               EateryRow(eatery: $eateries[identifiedBy: $0])
                            }
                        }
                    .onMove {
                        eateries.move(fromOffsets: $0, toOffset: $1)
                        EateriesApp.save()
                    }.onDelete {
                        eateries.remove(atOffsets: $0)
                        EateriesApp.save()
                    }
                }
                
                .navigationTitle("Favourite Eateries")
                .navigationBarItems(leading: EditButton(), trailing: Button( action: add)
                {
                    Image(systemName: "plus")
                    
                }
                    )
                     .listStyle(InsetGroupedListStyle())
            }
        }
        
    }
    
    func add() {
        eateries.append(Eatery(name: "Eatery", location: "Insert location here", notes: "Insert notes here", reviews: ["Insert reviews here"], url: "https://i.imgur.com/y3MMnba.png"))
        EateriesApp.save()
    }
}

I get this error on the line with the NavigationLink:

Unnamed argument #2 must precede argument 'destination'

For further clarity this is how I've used the "eatery" variable in the EateryDetail and EatertyRow views:

struct EateryDetail: View {
    @Binding var eatery: Eatery
struct EateryRow: View {
    @Binding var eatery: Eatery

And here is my code for Eatery which is defined in a file called eateries.swift:

import Foundation

struct Eatery: Codable, Identifiable {
    var id = UUID()
    var name: String
    var location: String
    var notes: String
    var reviews: [String] = []
    var url: String = ""
}

In eateriesApp.swift this is also defined:

import SwiftUI

@main
struct EateriesApp: App {
    @State var model: [Eatery] = EateriesApp.model
    static var model: [Eatery] = {
        guard let data = try? Data(contentsOf: EateriesApp.fileURL),
              let model = try? JSONDecoder().decode([Eatery].self, from: data) else {
        return [elCaminoCantina, theFineDine, nightBites, theRiverRodeo, theCozyKitchen, theElegantEatery]
        }
        return model
    }()
    static var modelBinding: Binding<[Eatery]>?

    var body: some Scene {
        EateriesApp.modelBinding = $model
        return WindowGroup {
            ContentView(eateries: $model)
        }
    }

Solution

  • You should need to use .indices in ForEach(eateries).

    Like this

    ForEach(eateries.indices) { index in
        NavigationLink(destination: EateryDetail(eatery: $eateries[index])) { //error here
            EateryRow(eatery: $eateries[index])
        }
    }
    

    The problem is you are using a shorthand variable ($0). When you used $0 inside the NavigationLink then $0 is considered for NavigationLink not ForEach. so now both $0 are in conflict in your case.

    You can check with the below code. In below code now not produce any error because now there is no use $0 inside the NavigationLink

    ForEach(eateries) {
        Text($0.name)
        NavigationLink(destination: EateryDetail(eatery: $eateries[identifiedBy: $0])) {
            Text("$0.name")
        }
    }
    

    Another solution is to use one variable and store your $0 data like this.

    ForEach(eateries) {
        let eaterie = $0 //<--- Here
        NavigationLink(destination: EateryDetail(eatery: $eateries[identifiedBy: eaterie])) { //<--- Here
            EateryRow(eatery: $eateries[identifiedBy: eaterie]) //<--- Here
        }
    }