【SwiftUI】NavigationViewを使用したアプリをiPadで表示させたら身に覚えのない白いViewが表示された時の対処法

2022.02.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

NavigationViewを使用したアプリの開発をしていて、iPhoneだと想定の動きをしていたのですが、検証の為にiPadで表示してみると身に覚えのない白い画面が表示された。

その原因と解決方法を調べたので記載します。

環境

  • Xcode 13.2.1
  • iOS 15.0

現象

ContentViewのコードはこのようになっています。

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 10) {
                Text("TOP画面です")
                NavigationLink("次のViewへ", destination: DestinationView())
            }
        }
    }
}

iPhoneで表示した時

TOP画面ですというテキストが表示され、想定通りの挙動をしています。

iPadで表示した時

身に覚えのない画面が表示されました。

TOP画面 Backを押した時

landscapeで表示

どうやらNavigationViewを使用した際にiPadでは、Master-Detail(Split view)の挙動になっているようです。MasterとなるViewが配置されていない為、身に覚えのない空白のViewが表示されている状態になっています。

ちなみにiPhone 13 Max Proのように画面サイズの大きいiPhoneを横向きにした際にも同じような挙動になりました。

解決方法

今回はiPhoneでもiPadでも同じような挙動にしたいという前提での解決方法です。

navigationViewStyleをstackに設定する

NavigationViewNavigationViewStyle.stackを適用すると、解決します。

.navigationViewStyle(.stack)

stackを適用させたコード

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 10) {
                Text("TOP画面です")
                NavigationLink("次のViewへ", destination: DestinationView())
            }
        }
        .navigationViewStyle(.stack)
    }
}

プレビュー

想定通りの表示がされました。

navigationViewStyle(_:)

navigationViewStyleNavigationViewにスタイルを設定出来るメソッドで、公式ドキュメントに記載がある通り、横向きのiPadなどの画面が広い環境では、NavigationViewはデフォルトで複数の列と共に表示されるようです。

今回の現象は、このデフォルト設定が原因のようでした。

stack

一度に1つの上面Viewのみを表示することを強制できるスタイルで、このスタイルを適用することで画面が広い場合でも、NavigationViewが1つのViewしか表示しないように出来ます。

なので、navigationViewStyle.stackを適用させることでiPadでもiPhoneと同様の動きになるようになりました。

おまけ MasterViewを表示させてみる

今回の解決したかった方針とは違いますが、Master-Detail(Split view)の挙動になっているといことで、Master Viewを表示させてみる方法も記載しておきます。

I am the masterというテキストが表示されるViewを作成しました。

struct MasterView: View {
    var body: some View {
        Text("I am the master")
            .font(.system(size: 30, weight: .black))
    }
}

作成したMasterViewMaster-Detailのマスターとして設定してみた

struct ContentView: View {
    var body: some View {
        NavigationView {
            VStack(spacing: 10) {
                Text("TOP画面です")
                NavigationLink("次のViewへ", destination: DestinationView())
            }
            MasterView()
        }
    }
}

それらしいSplit Viewが出来ました!

おわりに

ハマってしまった問題を解決する為に調べていると、Master-Detailでの表示方法を知る事が出来ました。嬉しかったです。

参考