Search code examples
iosswiftnavigationview

How to display a detailed view on startup for a NavigationView (SwiftUI)


This tutorial uses a NavigationView to display a List of elements which can be clicked, leading to a detailed view, LandmarkDetail. On an iPhone, the UI uses the StackNavigationViewStyle() which looks and works fine, but on an iPad the NavigationView is displayed on the side. I want to be able to fill up the remaining space with a detailed view (see below).

Actual vs desired output

I have tried to display the detailed view, LandmarkDetail, beside the NavigationView like so:

var body: some View {
        NavigationView {
            List {
                Toggle(isOn: $showFavoritesOnly) {
                    Text("Favorites only")
                }

                ForEach(filteredLandmarks) { landmark in
                    NavigationLink(destination: LandmarkDetail(landmark: landmark)) {
                        LandmarkRow(landmark: landmark)
                    }
                }
            }
            .navigationTitle("Landmarks")
            
            LandmarkDetail(landmark: ModelData().landmarks[0])
        }
    }

This approach works fine for the iPad, but produces unexpected results (overlapping tiles, etc.) on the iPhone (see below). Is there a better way for achieving my desired results?

enter image description here

Thanks for any help and I apologise about potential obvious mistakes, etc. This is my first time using SwiftUI and there are noticeably less resources available than for Android development.


Solution

  • Creating a modifier which programmatically assigned the NavigationView style depending on the target device fixed this issue.

    extension View 
    {
        func navigationStyleModification() -> some View
        {
            if UIDevice.current.userInterfaceIdiom == .phone
            {
                return AnyView(self.navigationViewStyle(StackNavigationViewStyle()))
            } else
            {
                return AnyView(self.navigationViewStyle(DefaultNavigationViewStyle()))
            }
        }
    }
    

    The modifier can be called via:

    NavigationView 
    {
        ...
    }.navigationStyleModification()
    

    I hope this helps someone who has a similar issue.