0

I have a NavigationView/List combination that allows programmatic selection. The basic concept is similar to the one described here: https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-programmatic-navigation-in-swiftui

With so many things, this works fine on iOS, but on macOS there's an issue: the EmptyView from the NavigationView becomes visible as soon as an item is selected:

enter image description here

Does anybody know how to remove this unwanted EmptyView()?

Here's a demo project:

struct ContentView: View {
    @ObservedObject private var state = State()

    var body: some View {
        NavigationView {
            VStack {
                List(state.items, id: \.self, selection: $state.selected) { item in
                    Text(item)
                        .buttonStyle(.borderless)
                }

                // navigation to the detail view if an item is selected
                if let selected = state.selected {
                    NavigationLink(
                        destination: Text(selected),
                        isActive: state.hasSelectionBinding
                    ) {
                        EmptyView()
                    }
                }
            }
        }
    }
}

class State: ObservableObject {
    @Published var items: [String] = ["Item 1", "Item 2", "Item 3"]
    @Published var selected: String?

    var hasSelectionBinding: Binding<Bool> {
        Binding(
            get: { self.selected != nil },
            set: {
                if $0 == false {
                    self.selected = nil
                }
            }
        )
    }
}

EDIT 1: I've tried putting the NavigationLink into a background modifier on the stack, but now the "Empty View" appears next to "Item 3":

    var body: some View {
        NavigationView {
            VStack {
                List(state.items, id: \.self, selection: $state.selected) { item in
                    Text(item)
                        .buttonStyle(.borderless)
                }
                
            }
            .background(Group {
                // navigation to the detail view if an item is selected
                if let selected = state.selected {
                    NavigationLink(
                        destination: Text(selected),
                        isActive: state.hasSelectionBinding
                    ) {
                        EmptyView()
                    }
                }
                
            })
        }
    }
6
  • Put it in the .background Commented Mar 1, 2022 at 14:47
  • @loremipsum: I've just tried putting the block with the NavigationLink into the background of the VStack, but now the "EmptyView" appears next to the last item of the list. Commented Mar 1, 2022 at 15:02
  • Add an edit section to you question showing what you tried just now. Commented Mar 1, 2022 at 15:16
  • 1
    I am thinking this is a bug. init(destinationName:isActive:label:) initializer shows the ghost image. NavigationLink(_:tag:selection:destination:) does not. Commented Mar 1, 2022 at 16:09
  • 1
    SwiftUI for macOS is really annoying, so many things just don't work as they should... Commented Mar 1, 2022 at 17:18

1 Answer 1

0

you could try this workaround in your first ContentView code:

NavigationLink("",                // <--- here
    destination: Text(selected),
    isActive: state.hasSelectionBinding
).position(x: 9999, y: 9999)     // <--- here

No need for the EmptyView(). Note, I suggest you rename your State model, since SwiftUI already has a State struct.

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

5 Comments

Interesting workaround, but unfortunately it doesn't work for my real application. There I have one level more of navigation. I'm using a sidebar on level 1, then the list and the third level is the detail view. Using this workaround, the list column is split as soon as you select an item. This is probably an other detail view.
The code in my answer works for me. Are you saying it does not work for you? Or that the code you show does not represent your question? What system are you using?
The code I'm showing is a simplified version showing the same issue as my real code. It works flawlessly with the simplified example. Unfortunately, I can't post my real code as it's too complex.
you can try other modifiers, such as .scaleEffect(0.0001) instead of position(..). But I feel you are saying that solving the issue in the code you provide is not going to work in your "real" code, no matter what solution is proposed.
I will try. It seems that the additional level of navigation I have in my real code is causing even more issues. I'm still investigating. But thanks for your help anyway, it's very much appreciated.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.