2

Given this...

NavigationLink(destination: Text("Hello")) {
   Text("Press")
}

And this...

.sheet(isPresented: $viewModel.showComplete) {
   Text("Hello")
}

How can I make the sheet only open if a view opened by the NavigationLink doesn't currently exist?

Ian Warburton
  • 15,170
  • 23
  • 107
  • 189
  • In context of SwiftUI value type views your *"if a view opened by the NavigationLink doesn't currently exist"* is not clear. Would you give more details on the use-case? – Asperi Oct 04 '20 at 05:47
  • I struggled with this. `NavigationLink` creates a view. Is it open or not when `showComplete` is true? – Ian Warburton Oct 04 '20 at 10:58
  • You can use concept of so called lazy/defer view to avoid that. Consider in https://stackoverflow.com/a/61242931/12299030 or https://stackoverflow.com/a/60295011/12299030 – Asperi Oct 04 '20 at 11:40

1 Answers1

1

You may access the isActive parameter of NavigationLink and use it in a custom binding to determine whether to open the sheet.

Here is a simple demo:

struct ContentView: View {
    @State var showSheet = false
    @State var linkActive = false
    
    var binding: Binding<Bool> {
        .init(get: {
            showSheet && !linkActive
        }, set: {
            showSheet = $0
        })
    }

    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(
                    destination: DetailView(showSheet: $showSheet),
                    isActive: $linkActive
                ) {
                    Text("Go to...")
                }
                Button("Open sheet") {
                    self.showSheet.toggle()
                }
            }
        }
        .sheet(isPresented: binding) {
            Text("Hello")
        }
    }
}

struct DetailView: View {
    @Binding var showSheet: Bool

    var body: some View {
        Button("Open sheet") {
            self.showSheet.toggle()
        }
    }
}
pawello2222
  • 46,897
  • 22
  • 145
  • 209
  • Your code works but mine isn't updating `$linkActive`. It's always false. – Ian Warburton Oct 03 '20 at 23:09
  • Seems to work only when I have `print(linkActive)` in `binding`'s `get`. – Ian Warburton Oct 04 '20 at 13:55
  • Also, this doesn't work if there are mulitple NavigationLink. For example in a ForEach. The binding triggers all of the links. – Ian Warburton Oct 04 '20 at 19:52
  • @IanWarburton Then you can take a look at [NavigationLink(destination:tag:selection:)](https://developer.apple.com/documentation/swiftui/navigationlink/init(destination:tag:selection:label:)) and use `selection` instead of `isActive`. – pawello2222 Oct 04 '20 at 19:58