Skip to content

Fix missing toolbar on SwiftUI keyboard on iOS 26 and above.#21

Open
Cheeezcake wants to merge 1 commit into
hackiftekhar:mainfrom
Cheeezcake:bug/missingToolbar
Open

Fix missing toolbar on SwiftUI keyboard on iOS 26 and above.#21
Cheeezcake wants to merge 1 commit into
hackiftekhar:mainfrom
Cheeezcake:bug/missingToolbar

Conversation

@Cheeezcake
Copy link
Copy Markdown

Description

Fix keyboard toolbar disappearance after navigation or app backgrounding.

Root cause analysis

The previous implementation used UIApplication.didBecomeActiveNotification to call reloadInputViews(). This approach had two major flaws:

  1. It only handled app backgrounding, but the same problem occurs after any event that temporarily hides the keyboard without resigning first responder (e.g., navigation push/pop, modal presentation). In those cases didBecomeActive never fires, so the toolbar was never restored.

  2. Timing issue – even for the background case, didBecomeActive fires before the keyboard has fully reappeared. Calling reloadInputViews() at that moment has no effect because the keyboard system isn't ready yet.

The correct trigger is UIResponder.keyboardDidShowNotification – it fires exactly when the keyboard is on screen and ready, regardless of why it reappeared (background, navigation, window overlay, etc.).

Proposed solution

Subscribe to keyboardDidShowNotification and call reloadInputViews() whenever the keyboard appears and the current textInputView is managed by the toolbar manager.

private func addKeyboardDidShowObserver() {
    NotificationCenter.default
        .publisher(for: UIResponder.keyboardDidShowNotification)
        .compactMap { [weak self] _ in self?.textInputView }
        .sink { [weak self] textInputView in
            self?.showLog("Keyboard did show, reloading input views for \(textInputView)")
            self?.reloadInputViews()
        }
        .store(in: &storage)
}

Benefits

  • Works for all scenarios where the keyboard reappears without a new beginEditing event (background, navigation, modal presentation, window overlay).
  • No reliance on didBecomeActive or arbitrary delays.
  • Uses the exact moment when the keyboard is ready, avoiding timing issues.

Known limitation

When the user taps a text field for the first time, the sequence is:

  1. textDidBeginEditing → triggers reloadInputViews() via IQTextInputViewNotification (expected).
  2. keyboardDidShow → triggers reloadInputViews() again via the new observer.

This results in a double refresh of the toolbar. In practice it's harmless (the toolbar is simply configured twice with the same state), but it's an inefficiency.

If this double call is considered critical – or if you have a better approach – please feel free to propose your own solution. I’m open to alternatives.

Testing

  • Simulator and device (iOS 26)
  • Scenarios tested:
    • Background → foreground with active text field
    • Push/pop navigation while editing
    • Present/dismiss modal while editing
    • Overlapping with another UIWindow (e.g., system alert, custom window)
    • Initial tap on a text field (double call observed but no visual glitch)

Fixes #15

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Tool bar is hidden when coming back to app from background. (iOS 26)

1 participant