10

When adding a NavigationLink in SwiftUI the destination is presented twice, ex: I tap on the NavigationLink and it pushes my destination but when I dismiss the destination, via the back button or the swipe gesture it pushes the destination again without taping on the link. Here is the part of my code that handles the link:

var body: some View { HStack(spacing: 8.0) { ForEach(part.getReference()) { (imageRef: ReferenceImage) in ZStack(alignment: .topTrailing) { Image(uiImage: imageRef.getUIImage()) .resizable() .frame(width: 90, height: 90) .cornerRadius(6) .onLongPressGesture { print("looong") self.managedObjectContext.delete(imageRef) do { try self.managedObjectContext.save() } catch { print("error deleting: \(error.localizedDescription)") } } ZStack(alignment: .center) { Circle() .foregroundColor(Color.appColors.lightRose) .opacity(0.7) .frame(width: 35, height: 35) Image(systemName: "arkit") .imageScale(.large) } NavigationLink(destination: ZStack { Color.appColors.rose .edgesIgnoringSafeArea(.top) ReferenceARSwiftUIView(currentImage: imageRef.getUIImage()) .navigationBarTitle("AR Reference") } ) { EmptyView() .frame(width: 90, height: 90) } } }.animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5)) 

EDIT 01: As suggested I removed a bit of the noise in the code:

var part: Part var body: some View { HStack(spacing: 8.0) { ForEach(part.getReference()) { (imageRef: ReferenceImage) in ZStack(alignment: .topTrailing) { Image(uiImage: imageRef.getUIImage()) .resizable() .frame(width: 90, height: 90) .cornerRadius(6) NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage())) { EmptyView() .frame(width: 90, height: 90) } } }.animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5)) 

EDIT 02: I think I narrowed down, basically if I remove the ForEach the NavigationLink pushes correctly to the next View. Also depending on the number of itens I have on my array for the ForEach the number of pushes is the same.

7
  • Any chance you could strip out and/or add things to your code for us to duplicate your issue? You have several things (Color.appColors.lightRose, Image, unneeded stacks) that really add noise. Maybe if you strip it down to NavigationView, NavigationLink, and maybe the ForEach to have us duplicate your issue, you might find it's working... and at that point you can add back in the rest to see why the code you posted isn't. Commented Sep 15, 2019 at 18:24
  • Okay a have removed most of the noise from the code, I think 😅 Commented Sep 15, 2019 at 20:31
  • I may have narrowed down the problem, I explained on the edit 02 Commented Sep 15, 2019 at 20:42
  • Thanks, hope I didn't offend you. Two thoughts. (1) I rarely see a ForEach without a List. Would this help? hackingwithswift.com/quick-start/swiftui/… More, (2) I actively check this site for the SwiftUI tag. I recall several questions with regards to both List nd NavigationLink (even Button) behavior in loops. Have you searched this site for those? Truth is, I stopped using the combination of NavigationView and List because of how... raw... SwiftUI is compared to UIKit, Commented Sep 15, 2019 at 21:45
  • 1
    I had the same issue. I believe there may be a bug in SwiftUI when using NavigationLink within ForEach. I could not get it to work with ScrollView as suggested below. I am only able to get it working if I don't use ForEach. Commented Nov 9, 2019 at 16:40

4 Answers 4

11

I'm sure that Part conforms to Identifiable protocol and has id property.

The destination of the NavigationLink is presented multiple times because you have multiple instances of Part that have the exact same identity id in the forEach loop.

Just make sure that each instance of Part has a unique id and everything will work as expected.

Sign up to request clarification or add additional context in comments.

1 Comment

6

I solved this by setting the NavigationLink's tag to the unique id of the model item.

Assuming you have an id for your imageRef, ReferenceImage class.

var part: Part var body: some View { HStack(spacing: 8.0) { ForEach(part.getReference()) { (imageRef: ReferenceImage) in ZStack(alignment: .topTrailing) { Image(uiImage: imageRef.getUIImage()) .resizable() .frame(width: 90, height: 90) .cornerRadius(6) NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage()), tag: imageRef.id) { EmptyView() .frame(width: 90, height: 90) } } }.animation(.interpolatingSpring(stiffness: 0.5, damping: 0.5)) 
NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage()), tag: imageRef.id) 

1 Comment

I am getting this issue even without ListView
1

Yeah changing List to ScrollView helped me in a similar situation.

ScrollView { if !usersViewModel.isLoading { ForEach(self.usersViewModel.users, id: \.id) { user in NavigationLink(destination: UserDashboardView(showDashboardDetail: $showDashboardDetail, user: user)) { VStack(alignment: .leading) { NetworkCardView(user: user) } .frame(width: screen.size.width - 60, height: 250) .padding(.top) } } .listRowBackground(AppColor()) } } 

Comments

0

I wasn't able to reproduce your issue, because even the stripped down version contains types declared by you, but not included in the question.

A couple of things:

If you want to use NavigationLink, the view needs to be embeded in a NavigationView.

If you are using ForEach inside an HStack there is a chance you are going to run out of space to display all the elements, so it would be a good idea to wrap it in a ScrollView.

Last, but not least: inside ForEach you have to make NavigationLink your top level view and make any other views its content:

var body: some View { NavigationView { ScrollView(.horizontal) { HStack { ForEach(part.getReference()) { (imageRef: ReferenceImage) in NavigationLink(destination: ReferenceARSwiftUIView(currentImage: imageRef.getUIImage())) { Image(uiImage: imageRef.getUIImage()) .resizable() .frame(width: 90, height: 90) .cornerRadius(6) } } } } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.