I have a SwiftUI View containing a basic NavigationStack
structure. I host this in a UIHostingController
and display modally as a sheet in UIKit using UIViewController.present()
.
Problem: When I rotate my iOS device to landscape from portrait, the navigation bar's back button extends past the safe area into the left corner of the device. Then, rotating back to portrait the back button is pushed further towards the center - not matching the intended position. (see images below).
Is there an API call I am missing to handle this rotation case? Thanks!
Code Example
SwiftUI view - ContentView.swift
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
Form {
NavigationLink {
Form {
Text("Hello")
}
.navigationTitle("Filter")
.navigationBarTitleDisplayMode(.inline)
} label: {
Text("Filter")
}
}
.navigationTitle("Filter")
.navigationBarTitleDisplayMode(.inline)
}
}
}
Main UIKit ViewController - ViewController.swift
import UIKit
import SwiftUI
class ViewController: UIViewController {
let swiftUIView = ContentView()
var hostingController: UIHostingController<ContentView>?
override func viewDidLoad() {
super.viewDidLoad()
hostingController = UIHostingController(rootView: swiftUIView)
guard let hostingController else { return }
hostingController.modalPresentationStyle = .formSheet
// Immediately present modally
DispatchQueue.main.async {
self.present(hostingController, animated: true)
}
}
}
More Detail
The issue only seems to appear for sheet modal presentation including these UIModalPresentationStyle
:
.formSheet
.pageSheet
.popover
The issue does not appear in an app with SwiftUI app lifecycle or when using UIKit and adding the hosting controller as a child view controller. This specifically happens when presenting modally and when the view gets rendered as a sheet.
I tried various combinations of UIHostingController.sizingOptions
and UIHostingController.safeAreaRegions
, but never found something that fixed the issue.
To Build and Reproduce
- Make a new Xcode project > iOS > App > Storyboard UI
- Add file
ContentView.swift
with contents above. - Replace contents of existing file
ViewController.swift
with contents above. - Set minimum deployment target to iOS 18
- Build and deploy to device running iOS 18.
- Hold device in portrait.
- Rotate device to landscape - observe back button extends past safe area.
- Rotate device to portrait - observe back button is shifted too far towards the center.
Device & Builds Specs
- iOS 18.6.2 - minimum deployment of 18.0
- Devices Observed:
- iPhone 12 Pro Max
- iPhone 16 Pro Max
- Xcode 26
Image Examples