I am building a custom suggestion/autocorrection feature in an iOS app. It must detect accidental adjacent keypresses and compare this to a known word list to suggest the word it thinks the user intended to type.
For example, if the custom word list contains cat
, dog
, monkey
, and the user types cst
, the app can determine that the most likely word was cat
(because s
is adjacent to the a
key)
This will work on a standard QWERTY keyboard, but what happens if the user is using an AZERTY keyboard?
For the autocorrect/suggest to work reliably, the app must be able to detect the keyboard layout in use.
In iOS, it is possible to obtain a UITextInputMode
object from a UITextField
. This object has a primaryLanguage
(string) property, which will display the locale (e.g. en-GB
), but this does not contain enough granularity to distinguish between English (Australia) QWERTY
and English (Australia) AZERTY
. In both cases, the primaryLanguage
is en-AU
.
Is it possible to detect the keyboard layout in iOS?
I have not been able to find a clean solution to this problem. Maybe this would be worth a TSI ticket to discuss it with Apple employees.
I know that this will not be a satisfying answer, but I would still like to share my thoughts here for future readers:
Private API of UITextInputMode:
textField.textInputMode?.value(forKey: "identifierWithLayouts")
This will return a string like de_DE@sw=QWERTZ-German;hw=Automatic
from which you can infer the keyboard layout.
UserDefaults
UserDefaults.standard.object(forKey: "AppleKeyboards")
This will return a list of all keyboards that the user has installed. In most cases, this will only be one language (besides the emoji keyboard). For example:
Optional(<__NSCFArray 0x600003b8e6c0>(en_US@sw=QWERTY;hw=Automatic,emoji@sw=Emoji))
You could also iterate over UserDefaults.standard.dictionaryRepresentation()
and search for QWERTZ/QWERTY/AZERTY within the values.
With much manual effort, you could maybe encode UITextInputModes
to binary data in all ambiguous cases like en_AU. Something like
NSKeyedArchiver.archivedData(withRootObject:textField.textInputMode, requiringSecureCoding: false)
can then be used to compare binary encodings of the user's textInputMode
at runtime.