iOS 27: SwiftUI keyboard safe area is not restored after returning to a UIHostingController

I have a SwiftUI view embedded in a UIHostingController. It contains a numeric text field at the top and a .borderedProminent button at the bottom.

The text field is automatically focused when the view appears. The bottom button pushes another instance of the same hosting controller.

On the initial appearance, SwiftUI correctly positions the button above the keyboard. However, after navigating back from VC2 to VC1, the text field is focused and the keyboard is visible, but the button remains behind the keyboard. This occurs regardless of whether VC2 is closed using the navigation bar back button or the interactive back gesture.

This appears to be an iOS 27 regression involving SwiftUI keyboard avoidance inside a UIHostingController.

The issue is especially problematic with a numeric keyboard because it has no Return or Done key. If the covered button is the primary way to continue or dismiss the keyboard, the user can no longer access it.

Interestingly, the button is repositioned correctly as soon as I begin moving the app into the background. This suggests that SwiftUI still knows about the keyboard safe area but does not update the layout correctly when the hosting controller reappears after being popped to.

Minimal reproducible example

import SwiftUI
import UIKit

final class NumericInputHostingController:
    UIHostingController<NumericInputView> {

    init() {
        super.init(
            rootView: NumericInputView(onContinue: {})
        )

        rootView = NumericInputView { [weak self] in
            self?.navigationController?.pushViewController(
                NumericInputHostingController(),
                animated: true
            )
        }
    }

    @available(*, unavailable)
    @MainActor required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

struct NumericInputView: View {
    @State private var value = ""
    @FocusState private var isTextFieldFocused: Bool

    let onContinue: () -> Void

    var body: some View {
        VStack(spacing: 24) {
            TextField("Enter a number", text: $value)
                .keyboardType(.numberPad)
                .focused($isTextFieldFocused)
                .padding(.horizontal, 16)
                .frame(height: 52)
                .background {
                    RoundedRectangle(cornerRadius: 10)
                        .stroke(
                            Color.accentColor,
                            lineWidth: 1.5
                        )
                }

            Spacer()

            Button("Open Another", action: onContinue)
                .buttonStyle(.borderedProminent)
                .controlSize(.large)
                .frame(maxWidth: .infinity)
        }
        .padding(20)
        .background(Color(.systemBackground))
        .onAppear {
            DispatchQueue.main.async {
                isTextFieldFocused = true
            }
        }
        .onDisappear {
            isTextFieldFocused = false
        }
    }
}

The initial controller is embedded in a navigation controller:

let controller = NumericInputHostingController()
let navigationController = UINavigationController(
    rootViewController: controller
)

Steps to reproduce

  1. Present VC1.
  2. VC1 automatically focuses the numeric text field.
  3. Confirm that the bottom button is above the keyboard.
  4. Tap the button to push VC2.
  5. Navigate back to VC1.
  6. VC1 focuses its text field and displays the numeric keyboard.
  7. Observe that the bottom button is now behind the keyboard.
  8. Begin putting the app into the background.
  9. Observe that the button suddenly moves to the correct position above the keyboard.

UIKit’s keyboardLayoutGuide handles the equivalent UIKit layout correctly. Is this a known issue with keyboard safe-area updates when a UIHostingController reappears after navigation? Is there a supported SwiftUI solution that does not require observing keyboard notifications manually?

iOS 27: SwiftUI keyboard safe area is not restored after returning to a UIHostingController
 
 
Q