iOS: Dictation case change with custom keyboard

I implement a custom keyboard extension. On modern iPhones the dictation button will display in the lower right even when a custom keyboard is active. If you are in an empty text field with the sentence capitalization trait turned on (e.g., Messages), press the Mic button, and dictate something, it will appear with the first word capitalized. As it should. But when you hit the Mic button again to accept the result, the first word is suddenly changed to uncapitalized. With the system keyboard this final case change does not occur.

Why? How to prevent this?

More technical detail: I receive UITextInputDelegate-textWillChange and UITextInputDelegate-textDidChange events during dictation (always with the textInput parameter set to nil) and then a final textDidChange with the lowercased text when accepting at the end.

Show us your code. It might be something you're doing.

Unfortunately it's part of a pretty large project and I haven't been able to reproduce the issue with a simpler one. It's hard to understand what in my own code could be driving it though since I would assume the dictation service is just interacting with the text field and the keyboard plays no role except to be informed viaUITextInputDelegate-textDidChange after the text is entered. No other calls to the keyboard happen, and in any case the factors determining casing are the UITextInputTraits and context in the text field.

Some more data points. Many people have reported this post-dictation lowercasing problem starting a few years ago, which can be found for example searching Google for 'iphone dictation flipping case' and going to the Reddit results. At the time it occurred for all third-party keyboards and not the stock one. However now it does NOT occur for major third-party keyboards such as Gboard.

Also, if I reproduce this, then switch to another keyboard without the problem, dictate there, and then switch back to my keyboard, the problem is gone. It seems like the dictation system is somehow asking the keyboard for information, presumably about the capitalization context in the text field, and for some reason my keyboard doesn't answer. After it gets the information from another keyboard though, it caches this and then uses it for subsequent dictations even in the absence of an answer. However this is puzzling because the keyboard subclasss is not responsible nor exposes any state relating to this – it is the responsibility of the text field which passes a proxy exposed as a proxy by the superclass.

iOS: Dictation case change with custom keyboard
 
 
Q