J'essaie de savoir quel séparateur décimal est utilisé par le clavier décimal dans iOS, afin de pouvoir convertir les chaînes entrées par l'utilisateur en nombres avec NumberFormatter
et vice-versa.
Comme je veux pré-remplir le champ de texte avec une valeur existante, il me faut un formateur de nombres utilisant le même séparateur décimal que le clavier du pavé décimal.
La langue sur laquelle mon appareil est configuré (allemand, Allemagne) utilise une virgule comme séparateur décimal. J'ai configuré iOS pour avoir le clavier allemand comme clavier principal et actif et l'anglais (US, QWERTY) comme clavier secondaire.
L'application sur laquelle je travaille n'a qu'une localisation de base, qui est l'anglais. Dans les paramètres du schéma, la région et la langue sont définies sur les valeurs par défaut du système.
Si j'exécute mon application, le séparateur décimal utilisé par le clavier décimal est ".", Qui est le séparateur décimal utilisé par le clavier en-US, mais pas par le clavier de-DE. Le clavier alphabétique normal montre la disposition du clavier allemand.
Si je supprime le clavier en-US sur le périphérique iOS, le séparateur décimal devient ",".
Comment puis-je savoir de manière fiable quel séparateur décimal est utilisé par le clavier décimal?
Aucune des solutions que j'ai essayées jusqu'à présent ne fonctionne:
decimalSeparator
of NumberFormatter
donne toujours ",".Locale.current.decimalSeparator
renvoie toujours "," également.textField.textInputMode?.primaryLanguage
pour déterminer les paramètres régionaux renvoie toujours de-DE
.Bundle.main.preferredLocalizations
pour déterminer la localisation utilisée par l'application renvoie toujours en
.Voici comment le formateur de nombres est configuré:
let numberFormatter = NumberFormatter()
numberFormatter.minimumIntegerDigits = 1
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2
Edit: Il semble être possible de déterminer les paramètres régionaux utilisés par le pavé décimal en recherchant des correspondances entre les modes de saisie de texte actifs et les localisations d'application:
let inputLocales = UITextInputMode.activeInputModes.compactMap {$0.primaryLanguage}.map(Locale.init(identifier:))
let localizations = Bundle.main.preferredLocalizations.map(Locale.init(identifier:))
let locale = inputLocales.flatMap { l in localizations.map {(l, $0)}}
.filter { preferredLanguage, preferredLocalization in
if preferredLocalization.regionCode == nil || preferredLanguage.regionCode == nil {
return preferredLanguage.languageCode == preferredLocalization.languageCode
} else {
return preferredLanguage == preferredLocalization
}
}
.first?.0
?? Locale.current
numberFormatter.locale = locale
Cependant, cette solution présente plusieurs inconvénients:
D'après mon expérience, lorsque vous ne supportez que la localisation anglaise, le séparateur décimal dans le type de clavier décimal sera toujours .
. Vous devez donc forcer en_US
locale dans la NumberFormatter
lors de l'analyse d'un nombre à partir d'une chaîne.
Voici un extrait de code qui tente d’analyser d’abord en utilisant en_US
, puis d’essayer en utilisant Locale.current
.
func parseNumber(_ text:String) -> Double? {
// since we only support english localization, keyboard always show '.' as decimal separator,
// hence we need to force en_US locale
let fmtUS = NumberFormatter()
fmtUS.locale = Locale(identifier: "en_US")
if let number = fmtUS.number(from: text)?.doubleValue {
print("parsed using \(fmtUS.locale)")
return number
}
let fmtCurrent = NumberFormatter()
fmtCurrent.locale = Locale.current
if let number = fmtCurrent.number(from: text)?.doubleValue {
print("parsed using \(fmtCurrent.locale)")
return number
}
print("can't parse number")
return nil
}
J'apprécierais que Apple ajoute le séparateur décimal Locale.current
comme séparateur décimal pour les types de clavier décimaux, sinon nous aurions besoin d'ajouter la localisation pour tous les paramètres régionaux afin d'obtenir ce droit.