SwiftUI: Launching three column iPad app with the Sidebar Visible

Viewed 740

Using the below code it’s possible to create a basic three-column iPad layout.

@main
struct threepanelApp: App {
    var body: some Scene {
        WindowGroup {
            NavigationView {
                List(0..<10, rowContent: { i in
                    Text(String(describing: i))
                })
                .listStyle(SidebarListStyle())
                .navigationTitle("One")
                
                List(10..<20, rowContent: { i in
                    Text(String(describing: i))
                })
                .navigationTitle("Two")

                VStack {
                    Text("Panel Three")
                }
                .navigationTitle("Three")
            }
        }
    }
}

However, when the app launches, it does so in its two-column layout.

Two Column

What I'd like to achieve is the app launching in its three-column layout:

Three Column

Is this possible with SwiftUI 2?

2 Answers

Figured out a hacky way to do this:

Dip into UIKit in .onAppear, find the UISplitViewController, and set its preferredDisplayMode.

var body: some Scene {
        WindowGroup {
            NavigationView {
                List(0..<10, rowContent: { i in
                    Text(String(describing: i))
                })
                .navigationTitle("One")

                ListTwo()

                VStack {
                    Text("Panel Three")
                }
                .navigationTitle("Three")
            }.onAppear {
                let controller = UIApplication.shared.windows.first { $0.isKeyWindow }!.rootViewController
                guard let split = controller?.children[0] as? UISplitViewController else {
                    print("not a split view")
                    return
                }
                split.preferredDisplayMode = .twoBesideSecondary
            }
        }
    }

when adding this extension, then everything is expanded on app start:

extension UISplitViewController {

    open override func viewDidLoad() {
        super.viewDidLoad()
        preferredDisplayMode = .twoBesideSecondary
    }
}
Related