Skip to main content

Command Palette

Search for a command to run...

Presenting a Sheet from a Popover Will Disable the Keyboard in iOS (SwiftUI Bug)

SwiftUI contains a bug that occurs when keyboard, popover and sheet are used in combination. This post includes a workaround until it's fixed.

Updated
•2 min read•View as Markdown
Presenting a Sheet from a Popover Will Disable the Keyboard in iOS (SwiftUI Bug)
P

A starfish that specialises in iOS and macOS development. My projects are:

🧽 Clean Share
🎶 Lyrcs
🍋‍🟩 Squash (Video Compressor)

This is occurring as of Xcode 15.3 (15E204a) on simulator and device

There is a situation in Lyrcs where:

  1. UITextView has keyboard focus

  2. Popover appears from a button tap

  3. Sheet appears from the popover

When the user dismisses the sheet and popover, UITextView will no longer have keyboard focus but the user can no longer make the keyboard appear by tapping on the UITextView . If the user holds down on the text input then the caret appears but still no keyboard. Even when using iOS simulator, characters typed with the macOS keyboard do not appear in the text input.

This occurs with any keyboard focus element; UITextField, TextField, TextEditor etc.

This is demonstrated with the following sample code:

struct ContentView: View {
    @State private var text = ""
    @State private var isPopoverPresented: Bool = false
    @State private var isSheetPresented: Bool = false

    var body: some View {
        VStack {
            Button("Show Popover") {
                isPopoverPresented = true
            }
            .popover(isPresented: $isPopoverPresented, content: {
                Button("Show Sheet") {
                    isSheetPresented = true
                }
                    .presentationCompactAdaptation(.popover)
                    .sheet(isPresented: $isSheetPresented, content: {
                        Text("I am a sheet")
                    })
            })
            TextField("Enter text", text: $text)
        }
    }
}

Until this is fixed, Lyrcs uses the following workaround (placed on the VStack) which dismisses the keyboard when the popover is presented:

extension View {
    func workaround_dismissKeyboardWhenPopoverAppears(isPopoverPresented: Bool) -> some View {
        onChange(of: isPopoverPresented) { previous, new in
            if new, new != previous {
                UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder),
                                                    to: nil, from: nil, for: nil)
            }
        }
    }
}

This has been submitted to Apple (FB13802395).