UITextField的数字键盘:浮点数值使用点号而不是逗号

13
我正在使用一个文本字段,该字段从数字键盘中填充。
问题是,在很多本地区格式(例如所有欧洲国家),UITextField的数字键盘上有逗号而不是点号,因此每次我写一个小数时,UITextField都无法识别小数逗号,并将其四舍五入。例如,23.07变成了23。
我该如何解决这个问题?我考虑将textField固定在美国;这可能吗?如何实现?
我使用以下代码读取值:
var importo = (importoPrevistoTF.text as NSString).floatValue

展示你的代码。使用十进制逗号的国家比使用十进制点的国家更多,请参见:Decimal mark。哦,我无法相信美国仍然不使用公制单位系统!;-) - zaph
@zaph,总的来说,我们都是傻瓜。 :) 我们在学校里半心半意地教授公制系统。加拿大做得对。从70年代初开始,他们干脆停止了向孩子们教授“英制”系统并转而采用公制系统。 - Duncan C
@DuncanC 我们并不孤单,利比里亚和缅甸也不使用公制系统,就只有我们三个国家。 - zaph
1
在问题中添加了代码。我认为公制系统更聪明,我只是不明白为什么不能找到一个妥协来让每个人都使用逗号或点号... - Matte.Car
如果在 Swift 中已经有了,那就是重复的。 - Matte.Car
11个回答

24

Swift 4

extension String {
    static let numberFormatter = NumberFormatter()
    var doubleValue: Double {
        String.numberFormatter.decimalSeparator = "."
        if let result =  String.numberFormatter.number(from: self) {
            return result.doubleValue
        } else {
            String.numberFormatter.decimalSeparator = ","
            if let result = String.numberFormatter.number(from: self) {
                return result.doubleValue
            }
        }
        return 0
    }
}

"2.25".doubleValue // 2.25
"2,25".doubleValue // 2.25
使用 NumberFormatter 的本地化方法:
extension NumberFormatter {
    static let shared = NumberFormatter()
}
extension StringProtocol {
    var doubleValue: Double? {
        return NumberFormatter.shared.number(from: String(self))?.doubleValue
    }
}

游乐场测试

// User device's default settings for current locale (en_US)
NumberFormatter.shared.locale            // en_US (current)
NumberFormatter.shared.numberStyle       // none
NumberFormatter.shared.decimalSeparator  // "."
"2.7".doubleValue  // 2.7
"2,7".doubleValue  // nil
"$2.70".doubleValue  // nil

NumberFormatter.shared.numberStyle  = .currency
"2.7".doubleValue  // nil
"2,7".doubleValue  // nil
"$2.70".doubleValue  // 2.7


NumberFormatter.shared.locale  = Locale(identifier: "pt_BR") // pt_BR (fixed)
"2.7".doubleValue     // nil
"2,7".doubleValue     // nil
"R$2,70".doubleValue  // 2.7

NumberFormatter.shared.numberStyle = .none
"2.7".doubleValue      // nil
"2,7".doubleValue      // 2.7
"R$2,70".doubleValue   // nil

1
我承认之前没有看到这个问题...但是这个解决方案更好! - Matte.Car
这是一个次优解决方案。请参见 https://dev59.com/I10a5IYBdhLWcg3wmZoX#30152398 或 https://dev59.com/I10a5IYBdhLWcg3wmZoX#30151275,它们不假设本地化。 - SamB

15

可能是SO答案的重复,请使用NSNumberFormatter

Swift示例:

let number = NSNumberFormatter().numberFromString(numberString)
if let number = number {
    let floatValue = Float(number)
}

示例(Objective-C):

NSNumber *number = [[NSNumberFormatter new] numberFromString: numberString];
float floatValue = number.floatValue;

有一个奇怪的问题。对于某些区域格式,例如意大利语,点和逗号都可以使用,但对于其他格式,例如美国,点可以使用但逗号会崩溃;这怎么可能呢? - Matte.Car

12

目前还没有人直接解决这个问题。

也就是说,小数点分隔符是区域惯例。

iOS支持根据特定区域格式化数字。

如果您在纯粹的给定区域中工作,那么一切都应该正常工作。键盘应该接受具有正确小数分隔符的数字。

例如,在欧洲大多数国家,您将输入逗号作为小数分隔符。在这些国家输入一个点是错误的。来自这些国家的人不会这样做,因为它是错误的小数分隔符。欧洲用户会知道使用逗号作为小数分隔符,您无需做任何事情。

如果您在美国,则应使用句点。在美国使用逗号是错误的。

应使用数字格式化程序来显示小数。创建数字格式化程序时,默认情况下使用当前区域设置。

如果您需要将包含小数的字符串从一种语言环境转换为另一种语言环境,则应使用2个数字格式化程序。在源语言环境中使用格式化程序将字符串转换为浮点数。然后使用具有目标语言环境的格式化程序将数字转换为输出格式中的字符串。

只需在默认当前区域设置中创建一个数字格式化程序,然后创建第二个数字格式化程序并将其区域设置明确设置为要使用的其他区域。


5

这可能是此答案的复制,但由于原始答案使用Objective-C,这里提供一个Swift版本:

let label = "23,07"
let formatter = NSNumberFormatter()
let maybeNumber = formatter.numberFromString(label)
if let number = maybeNumber {
    println(number)   // 23.07
}

非常感谢!我刚刚翻译完Swift,然后看到了你的回答! - Matte.Car
2
问题在于 formatter.numberFromString(label) 可能会返回 nil,如果区域设置与字符串格式不匹配,则也会返回 nil - zaph

2

Swift 3:包含逗号的浮点数字符串使用float或double数值

extension String {
    var floatValue: Float {
        let nf = NumberFormatter()
        nf.decimalSeparator = "."
        if let result = nf.number(from: self) {
            return result.floatValue
        } else {
            nf.decimalSeparator = ","
            if let result = nf.number(from: self) {
                return result.floatValue
            }
        }
        return 0
    }

    var doubleValue:Double {
        let nf = NumberFormatter()
        nf.decimalSeparator = "."
        if let result = nf.number(from: self) {
            return result.doubleValue
        } else {
            nf.decimalSeparator = ","
            if let result = nf.number(from: self) {
                return result.doubleValue
            }
        }
        return 0
    }
}

例子:

"5,456".floatValue //5.456
"5.456".floatValue //5.456
"5,456".doubleValue //5.456
"5.456".doubleValue //5.456

"5,456".doubleValue.rounded() //5
"5,6".doubleValue.rounded() //6

1
我找到了一个解决方案:
let nf = NumberFormatter()
nf.locale = Locale.current
let numberLocalized = nf.number(from: txtAlcool.text!)

在我的情况下,我正在xcode上进行测试,一切都很正常,但在设备上进行测试时崩溃了。这是因为在巴西我们使用公制系统,用逗号分隔小数“,”。通过这种解决方案,它可以自动将逗号转换为点。

1
自从Swift的最新版本中NSNumberFormatter被NumberFormatter替换,我很高兴与您分享升级后的可能解决方案:
var numberFormatter: NumberFormatter()
importo = Float(numberFormatter.number(from: importoPrevistoTF.text!)!)

1

使用当前版本的Swift可工作的代码:

let amount = "8,35"

var counter: Int = 0
var noCommaNumber: String!
for var carattere in (amount) {
    if carattere == "," { carattere = "." }
    if counter != 0 { noCommaNumber = "\(noCommaNumber ?? "\(carattere)")" + "\(carattere)" } else { noCommaNumber = "\(carattere)" } // otherwise first record will always be nil
    counter += 1
}

let importo = Float(noCommaNumber)

0
你可以使用NumberFormatter并过滤不同的小数分隔符来进行转换:
func getDoubleFromLocalNumber(input: String) -> Double {
    var value = 0.0
    let numberFormatter = NumberFormatter()
    let decimalFiltered = input.replacingOccurrences(of: "٫|,", with: ".", options: .regularExpression)
    numberFormatter.locale = Locale(identifier: "EN")
    if let amountValue = numberFormatter.number(from: decimalFiltered) {
        value = amountValue.doubleValue
    }
    return value
}

0

Swift 4解决方案,不使用preferredLanguages,我遇到了fr_US和decimalPad的问题

extension String {

     func number(style: NumberFormatter.Style = .decimal) -> NSNumber? {
        return [[Locale.current], Locale.preferredLanguages.map { Locale(identifier: $0) }]
            .flatMap { $0 }
            .map { locale -> NSNumber? in
                let formatter = NumberFormatter()
                formatter.numberStyle = style
                formatter.locale = locale
                return formatter.number(from: self)
        }.filter { $0 != nil }
        .map { $0! }
        .first
    }
}

textfield.text?.number()?.floatValue

可选<Double>
  • some : 9.3000000000000007
- Can Aksoy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接