全てきれいに解決できる案があったので、シェアします。
1. 前提条件
前提条件として、
- watchOS 9+ では
NavigationStack
- watchOS 8 では
NavigationView { ... }.navigationViewStyle(.stack)
を使用します。
また、今後の SwiftUI のバージョンアップによる副作用を避けるため、watchOS 10 ではデフォルトの閉じるボタンを使用します。watchOS 8 では既定の Cancel ボタンを Close ボタンに置き換える処理を行います。
2. 親ビュー
遷移元のサンプルです。
import SwiftUI struct ContentView: View { var body: some View { Text("Root View") } } struct NavigationHost: View { @State private var isPresented = false var body: some View { Group { if #available(watchOS 9.0, *) { NavigationStack { ContentView() } } else { NavigationView { ContentView() } .navigationViewStyle(.stack) } } .sheet(isPresented: $isPresented) { SheetViewHost() } } }
3. シートビュー
import SwiftUI extension View { func block<Content>(@ViewBuilder _ transform: (Self) -> Content) -> Content { transform(self) } } struct SheetView: View { @Environment(\.dismiss) private var dismiss var body: some View { Text("Sheet View") .block { content in if #available(watchOS 10.0, *) { content } else { content.toolbar { // watchOS 8 では既定のキャンセルボタンを置き換え、 // watchOS 9 では閉じるボタンを追加します。 ToolbarItem(placement: .cancellationAction) { Button("Close", role: .cancel, action: dismiss.callAsFunction) } } } } } } struct SheetViewHost: View { var body: some View { if #available(watchOS 9.0, *) { NavigationStack { SheetView() } .block { content in if #available(watchOS 10.0, *) { content } else { content.navigationBarHidden(true) // 肝!! } } } else { NavigationView { SheetView() } .navigationViewStyle(.stack) .navigationBarHidden(true) // 肝!! } } }
最後に
これだけ覚えて帰ってください。sheet 自体が NavigationStack
の中になくても、親ビューで NavigationStack
を使っている状態で sheet を用いたい場合、.navigationBarHidden(true)
を使って親側のナビゲーション バーを非表示にすること。
これで全てうまくいきます。