1
votes

When using NavigationLink on the bottom of a view after ForEach it won't work if it is not visible.

I have a list of Buttons. If a button is pressed, it sets a Bool to true. This bool value now shows a NavigationLink which immediately activates because the passed binding is set to true. However, the link won't work if the array is too long because it will be out of sight once one of the first buttons is pressed.

This is my Code:

import SwiftUI

struct TestLinkView: View {
    @State private var linkIsActive = false
    
    var body: some View {
        NavigationView {
            VStack {
                Button(action: {
                    linkIsActive = true
                }) {
                    Text("Press")
                }
                
                NavigationLink(destination: ListView(linkIsActive: $linkIsActive), isActive: $linkIsActive) {
                    Text("Navigation Link")
                }
            }
        }
    }
}


struct ListView: View {
    
    var nameArray = ["Name1","Name2","Name3","Name4","Name5","Name6","Name7","Name8","Name9","Name10","Name11","Name12","Name13","Name14","Name15","Name16","Name17","Name18","Name19","Name20" ]
    @State private var showLink: Bool = false
    @State private var selectedName: String = ""
    @Binding var linkIsActive: Bool
    var body: some View {
        
        Form {
            ForEach(nameArray, id: \.self) { name in
                Button(action: {
                    selectedName = name
                    showLink = true
                }) {
                    Text(name)
                }
            }
            
            if showLink {
                NavigationLink(destination: NameView(selectedName: selectedName), isActive: $linkIsActive) {
                    EmptyView()
                }
            }
        }
        .navigationBarTitle("ListView")
    }
}

struct NameView: View {
    
    var selectedName: String
    
    var body: some View {
        Text(selectedName)
            .navigationBarTitle("NameView")
    }
}

What would work is to pass the NavigationLink with the if-condition inside the button label. However if I do that, the animation won't work anymore.

1

1 Answers

1
votes

You don't need it in Form, which is like a List don't create views far outside of visible area. In your case the solution is to just move link into background of Form (because it does not depend on form internals).

The following tested as worked with Xcode 12 / iOS 14.

    Form {
        ForEach(nameArray, id: \.self) { name in
            Button(action: {
                selectedName = name
                showLink = true
            }) {
                Text(name)
            }
        }
    }
    .background(Group{
        if showLink {
            NavigationLink(destination: NameView(selectedName: selectedName), isActive: $linkIsActive) {
                EmptyView()
            }
        }
    })