在iOS上获取小数键盘的小数分隔符

时间:2018-07-08 15:31:41

标签: ios uikit foundation

我试图找出iOS中的十进制键盘使用哪个十进制分隔符,因此我可以将用户输入的字符串转换为带有NumberFormatter的数字并返回。

由于我想用现有值预填充文本字段,因此我需要一个数字格式化程序,该数字格式化程序使用与小数键盘相同的小数点分隔符。


我的设备设置为的语言(德国,德国)使用逗号作为小数点分隔符。我已将iOS配置为以德语键盘为主要和活动键盘,以英语(美国,QWERTY)为辅助键盘。

我正在使用的应用程序只有一个基本的本地化语言,那就是英语。在方案设置中,区域和语言设置为系统默认值。

如果运行我的应用程序,则十进制键盘使用的十进制分隔符为“。”,这是en-US键盘而非de-DE键盘所使用的十进制分隔符。普通的字母键盘会显示德语键盘的布局。

如果我在iOS设备上卸下en-US键盘,则小数点分隔符将变为“,”。


如何可靠地确定小数键盘使用哪个小数分隔符?

到目前为止,我尚未尝试过的解决方案都可以使用

  • 使用decimalSeparator的预设NumberFormatter总是给出“,”。
  • 使用Locale.current.decimalSeparator也会始终返回“,”。
  • 使用textField.textInputMode?.primaryLanguage来确定语言环境总是返回de-DE
  • 使用Bundle.main.preferredLocalizations来确定应用程序使用的本地化总是返回en

这是配置数字格式器的方式:

let numberFormatter = NumberFormatter()
numberFormatter.minimumIntegerDigits = 1
numberFormatter.minimumFractionDigits = 0
numberFormatter.maximumFractionDigits = 2

编辑:通过查找活动文本输入模式和应用本地化之间的匹配,似乎可以确定小数点使用的语言环境:

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

但是此解决方案有几个缺点:

  1. 我不知道UIKit是否正是这样选择小数点分隔符。某些语言的行为可能有所不同
  2. 每次格式化数字时都必须计算该数字,因为用户可能会在应用程序运行时更换键盘。

1 个答案:

答案 0 :(得分:1)

我的经验是,当您仅支持英语本地化时,十进制键盘类型中的十进制分隔符将始终为.。因此,从字符串中解析数字时,您需要在en_US中强制使用NumberFormatter语言环境。

这是一个代码片段,它首先尝试使用en_US进行解析,然后尝试使用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
}

如果Apple将Locale.current十进制分隔符添加为十进制键盘类型的十进制分隔符,我将不胜感激,否则我们需要为所有语言环境添加本地化才能正确使用。