6

I need to implement an UI which close to the default Mail app in iPad and iPhone.

The App has two sections, typically, the master view will be displayed on the left side and detail view will be displayed in the right side in iPad.

In the phone, the master view will be displayed on whole screen, the detail view can be pushed as second screen.

How to implement it in the new SwiftUI

iOSProgrammingIsFun
  • 1,418
  • 1
  • 15
  • 32
Qing Xu
  • 2,704
  • 2
  • 22
  • 21

2 Answers2

24

There is not really a SplitView in SwiftUI, but what you describe is automatically accomplished when you use the following code:

import SwiftUI

struct MyView: View {
    var body: some View {
        NavigationView {
            // The first View inside the NavigationView is the Master
            List(1 ... 5, id: \.self) { x in
                NavigationLink(destination: SecondView(detail: x)) {
                    Text("Master\nYou can display a list for example")
                }
            }
            .navigationBarTitle("Master")
            // The second View is the Detail
            Text("Detail placeholder\nHere you could display something when nothing from the list is selected")
                .navigationBarTitle("Detail")
        }
    }
}

struct SecondView: View {
    var detail: Int
    var body: some View {
        Text("Now you are seeing the real detail View! This is detail \(detail)")
    }
}

This is also why the .navigationBarTitle() modifier should be applied on the view inside the NavigationView, instead of on the NavigationView itself.

Bonus: if you don't like the splitView navigationViewStyle, you can apply the .navigationViewStyle(StackNavigationViewStyle()) modifier on the NavigationView.

Edit: I discovered that the NavigationLink has an isDetailLink(Bool) modifier. The default value appears to be true, because by default the "destination" is presented in the detail view (on the right). But when you set this modifier to false, the destination is presented as a master (on the left).

cbjeukendrup
  • 3,216
  • 2
  • 12
  • 28
  • 1
    I hadn't found the `isDetailLink(()` modifier, so that solved a similar problem I had. THANK YOU!! – Ben Carroll Aug 14 '19 at 00:13
  • `isDetailLink()` is buggy on iPad iOS 13.1. The view will disappear as soon as you start interacting with it. – caram Oct 13 '19 at 10:02
  • 3
    How can I make the Master Column visible in portrait mode visible all the time. Swiping from the left in order to see it is not ideal as it is not intuitive imo. DoubleColumnNavigationViewStyle seems not to work on XCode Version 11.2 beta 2 nor on Xcode Version 11.1 ‍♂️ – simibac Oct 24 '19 at 06:10
  • 1
    @SimonBachmann Yes, swiping from the left is not intuitive, I agree with you! I haven’t found a solution for that yet, but when I find something I’ll let you know! – cbjeukendrup Oct 24 '19 at 08:47
  • Yeah that would be great! I think they will fix this in a future update. It seems to be a bug. Also I hope they add the possibility to dynamically change DoubleColumnNavigationViewStyle to StackNavigationViewStyle, such that you can navigate to fullscreen to (Column1 -> Column2 -> FullScreenView). This is not possible right now. – simibac Oct 24 '19 at 08:55
0

In iOS 16+, a split view can be created as follows:

@State private var employeeIds: Set<Employee.ID> = []

var body: some View {
    NavigationSplitView {
        List(model.employees, selection: $employeeIds) { employee in
            Text(employee.name)
        }
    } detail: {
        EmployeeDetails(for: employeeIds)
    }
}

You can configure both 2 and 3 column layouts.

Docs: https://developer.apple.com/documentation/swiftui/navigationsplitview

miken32
  • 42,008
  • 16
  • 111
  • 154
SimeonRumy
  • 363
  • 4
  • 9