swiftmacosswiftuinavigationsplitviewnavigationsplitviewvisibility

NavigationSplitViewVisibility.detailOnly not working in macOS


I've been having lots of problems with NavigationSplitView in SwiftUI under macOS (14.3 if it matters). The latest one is this: NavigationSplitViewVisibility.detailOnly doesn't seem to do anything, it just reverts to showing the 3 original columns. If anyone knows how to actually trigger NavigationSplitView to only display the detail area I will be eternally grateful.

This is the code that is not working:

import SwiftUI

struct ContentView: View {
    @State private var columnVisibility: NavigationSplitViewVisibility = .all
    private var cvString: String { "\(columnVisibility)"}
    
    var body: some View {
        NavigationSplitView(columnVisibility: $columnVisibility) {
            VStack {
                Text("Sidebar")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
            .background(.red)
        } content: {
            VStack {
                Text("Content")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
            }
            .background(.orange)
        } detail: {
            VStack {
                Spacer()
                Text("Detail")
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                
                HStack {
                    Text("Current Visibility:")
                        .bold()
                    
                    Text("\(cvString)")
                        .fontDesign(.monospaced)
                }
                
                Button("Next Visibility") {
                    self.columnVisibility = columnVisibility.next()
                }
                
                Spacer()
            }
            .background(.green)
        }
    }
}

// Extension just to toggle between Visibilities
extension NavigationSplitViewVisibility {
    func next() -> NavigationSplitViewVisibility {
        switch self {
        case .all: print("All -> DetailOnly"); return .detailOnly
        case .detailOnly: print("DetailOnly -> DoubleColumn"); return .doubleColumn
        case .doubleColumn: print("DoubleColumn -> All"); return .all
        default:
            print("Not handled.")
            return self
        }
    }
}

Solution

  • This is by-design. From the documentation of NavigationSplitViewVisibility,

    Some platforms don’t respect every option. For example, macOS always displays the content column.

    So the NavigationSplitViewVisibility values are more of a "suggestion".

    You may argue that .detailOnly on macOS should at least be like .doubleColumn instead of .all, but either way a "true" .detailOnly is not supported.