- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个 UILabel
来显示输入文本(它有十进制数字)。我想要做的是,UILabel
文本可以根据语言环境显示。例如-
"1234.56" should be shown as "1,234.56" for US locale, "1.234,56" for DE (Germany) locale and so on.
以下是我为实现这一目标所做的工作-
NSNumberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
NSNumberFormatter.locale = NSLocale(localeIdentifier: language)
NSNumberFormatter.maximumFractionDigits = 16
let displayVal: Double = NSNumberFormatter.numberFromString(displayText.text!).doubleValue
displayText.text = NSNumberFormatter.stringFromNumber(displayVal)
其中 displayText
是显示输入的 UILabel
。
它工作正常,直到 4 位数字,即“1234”显示为“1,234”(对于美国语言环境)。但是一旦添加了第 5 位数字,nil
就返回了 displayVal
常量变量。
我可以从函数定义中猜到格式化 displayText
文本字符串失败,当 numberFromString
尝试按照美国格式格式化它时,它可能是“1,2345”语言环境但失败,因为这不符合美国语言环境格式。
谁能提出解决这个问题的方法或更好的实现方法?
最佳答案
您可以执行类似以下操作,即去掉任何千位分隔符,从中获取一个数字,然后使用千位分隔符重新格式化:
@IBAction func didEditingChanged(_ sender: UITextField) {
guard let text = sender.text else { return }
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
// get thousands separator
let thousandsSeparator = formatter.groupingSeparator ?? ","
// strip thousands separators out
let stripped = String(text.filter { return String($0) != thousandsSeparator })
// now, re-insert them, if any
if let number = formatter.numberFromString(stripped) {
sender.text = formatter.stringFromNumber(number)
}
}
假设您将其连接到“编辑更改”以使其不断更新,这会引入一些问题。例如,要输入尾随小数位,您可能必须手动检查并允许保留:
@IBAction func didEditingChanged(_ sender: UITextField) {
guard let text = sender.text else { return }
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
// get thousands separator
let thousandsSeparator = formatter.groupingSeparator ?? ","
// strip thousands separators out
let stripped = String(text.filter { return String($0) != thousandsSeparator })
// see if decimal place found, and if so, set fractional digits accordingly
let decimalSeparator = formatter.decimalSeparator ?? "."
var fractionalDigits: Int?
if let decimalSeparatorIndex = text.range(of: decimalSeparator)?.lowerBound {
fractionalDigits = text[decimalSeparatorIndex...].count(of: "0123456789")
formatter.minimumFractionDigits = fractionalDigits!
}
guard
let number = formatter.number(from: stripped),
var result = formatter.string(from: number)
else {
// do whatever is appropriate if string isn't a number at all
return
}
// re-add trailing decimal place only if decimal separator was found, but no fractional digits were
if fractionalDigits == 0 {
result += decimalSeparator
}
// update text field
sender.text = result
}
请注意,它使用了这个小扩展:
extension StringProtocol {
func count(of string: String) -> Int {
return reduce(0) { $0 + (string.contains($1) ? 1 : 0) }
}
}
您还可以进行许多其他改进。例如,如果用户在编辑时不在文本字段的末尾,这将重置 selectedTextRange
。您可能还应该实现 shouldChangeCharactersIn
以确保您根本无法在 stripped
会失败的地方输入值。等等
但希望这说明了一种捕获文本输入并使用格式化的十进制数更新结果的方法。
有关 Swift 2 版本,请参阅 previous revision of this answer。
关于ios - 如何将 UILabel 文本格式化为特定于语言环境的 NSNumberFormatterStyle.DecimalStyle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38002898/
我是一名优秀的程序员,十分优秀!