How to call SwiftUI NavigationLink conditionally?

Viewed 605

I'm thinking how to conditionally permit to start NavigationLink when user has tapped it. In UIKit it is just obvious but in SwiftUI this seems to me a huge problem. I know that I could declare NavigationLink somewhere in my view i.e.

@State private var isFired = false

/* (...) */

NavigationLink(destination: AnotherView(), isActive: $isFired) { EmptyView() }

and call it like this

Button(action: {
    if /* check condition */ {
        self.isFired = true
    } else {
        print("condition is not fulfilled")
    }
}) {
    Image("my-image")
}

but... the problem is: my navigation links are created dynamically in a loop and are wrapping images in ScrollView, i.e.

ScrollView(.vertical) {
    ForEach(photos, id: \.self) { element in
        NavigationLink(destination: ImagePreviewView(photo: element)) {
            Image(uiImage: element.image)
        }
    }
}

How to conditionally allow to start the navigation link in the code above? For example: user tapps an image -> a password request is presented -> if the password is correct the navigation link fires, if not the app does something else (presents alert etc. doesn't matter)

1 Answers

Anyway it should be a button... something like

ScrollView(.vertical) {
    ForEach(photos, id: \.self) { element in
        Button(action: {
           // here call a function with callback provided if password
           // verification passed
           self.checkPassword { verified in
             if verified {
                self.photo = element  // store tapped element
                self.isFired = true   // << this might be called async
             }
           }
        }) {
            Image(uiImage: element.image)
        }
    }
}
.background(
   // activate link for tapped photo
   NavigationLink(destination: ImagePreviewView(photo: self.photo), 
      isActive: $isFired) { EmptyView() }
)
Related