【问题标题】:trying to convert a string to a decimal for iOS 13尝试将字符串转换为 iOS 13 的小数
【发布时间】:2019-09-29 02:50:06
【问题描述】:

我有一个应用程序,在 iOS 13 之前一切正常。我检查了一些帖子,但他们似乎在说我已经做过的事情。

我正在传递一个包含货币符号和格式的字符串,我想去掉它并使用字符串值。

func changeCurrencyToDecimal(stringNumber:String) -> Decimal {


    let numberFormatter = NumberFormatter()

    // Pull apart the components of the user's locale
    var locComps = Locale.components(fromIdentifier: Locale.current.identifier)
    // Set the specific currency code
    locComps[NSLocale.Key.currencyCode.rawValue] = options?.currencyCode // or any other specific currency code
    // Get the updated locale identifier
    let locId = Locale.identifier(fromComponents: locComps)
    // Get the new custom locale
    //numberFormatter.locale = Locale(identifier: locId)

    if(options?.currencyCode == nil) {
           print("There is no currency code so use the default locale")
           numberFormatter.locale = Locale.current
       }
       else{
           print("We have a currency code!")
           numberFormatter.locale = Locale(identifier: locId)
       }

    numberFormatter.numberStyle = .currency
    numberFormatter.currencySymbol = ""
    numberFormatter.decimalSeparator = ","  

    print("\(stringNumber) is the number being passed")

    let number = numberFormatter.number(from: stringNumber)

    // check to see if the number is nil and if so, return 0.

    print("\(number) is the number converted")
    if number == nil{
        return 0
    }
    else{
        print("\(number!) is the number")
        let amount = number?.decimalValue
        return amount!
    }

}

我传递的字符串示例:$300.00 $ 总是触发返回 nil。如果我通过 300.00,那么转换器就可以正常工作。但我需要能够检查用户为其设备设置的任何货币。

我正在检查的货币代码是 Apple 在 var currencyCode: String? { get } 选项中提供的货币代码,这正是我存储这些代码的位置。

numberFormatter 每次都产生 nil,这似乎是因为我的小数点没有被剥离其格式。

这在 iOS 13 之前同样有效,所以我猜测 Apple 方面发生了一些变化,我可能还没有遇到过。

更新 这是一个用户seniaro。用户输入金额。如果用户立即点击保存,我会将金额转换为小数以保存在 coredata 中。但是,如果用户关闭键盘,我会获取该金额并将其转换为字符串以显示货币符号。我允许用户设置他们的货币,所以使用区域设置对我不起作用,因为有时他们不使用该系统。因此,在关闭键盘并以正确的格式显示其数量后,我对其进行了编程,如果他们碰巧改变了数量并再次关闭键盘,并重复相同的步骤。货币符号被剥离,字符串被转换为小数。

我希望这能让您更好地了解它在我的应用中的工作原理。

更新 我添加了一个 if/else 语句来查看语言环境是否已设置或返回为零,如果是,则将其设置为 Locale.current

【问题讨论】:

  • 货币字符串是始终采用特定格式并带有特定的小数分隔符,还是用户以他们的区域设置习惯格式输入的字符串?为什么要将小数分隔符硬编码为逗号,但尝试使用句点解析十进制字符串?你为什么要跳过箍来设置语言环境?
  • 用户可以设置语言环境,所以我无法预测货币的格式。我正在尝试去除所有格式的货币,并使用该小数。跨度>
  • 如果用户在他们自己的语言环境中输入字符串,那么解决方案是微不足道的。删除您必须设置数字格式化程序的所有不必要的代码。创建它并设置样式。就是这样。不要设置除样式之外的数字格式化程序的任何其他属性。

标签: ios swift nsnumberformatter


【解决方案1】:

假设输入字符串使用设备的当前语言环境,您可以使用Locale.current 创建一个NumberFormatter,并将numberStyle 设置为货币。

我用一个小操场来测试它:

import Foundation

func changeCurrencyToDecimal(_ stringNumber: String) -> Decimal? {
  let numberFormatter = NumberFormatter()
  numberFormatter.numberStyle = .currency

  let number = numberFormatter.number(from: stringNumber)
  return number?.decimalValue
}

let numbersFormatted = ["$300", "$3,000.04", "3.000,04", "Wazaa", "3000000"]
numbersFormatted
  .map { changeCurrencyToDecimal($0) }
  .forEach { print($0 ?? "Not a value") }

打印出来:

  • 300
  • 3000.04
  • 不是一个值
  • 不是一个值
  • 3000000

如果您因此不断收到nil,则您设备的区域设置与您在问题中使用的示例字符串编号不同(300 美元)。

【讨论】:

  • 1.无需将语言环境设置为Locale.current。这是默认设置。 2. 此答案中代码的输出取决于运行代码的用户的语言环境。
  • 您说得对,无需将语言环境设置为当前,我将编辑答案。输出确实取决于设备的配置,但我认为函数返回 decimal 这就是 @icekomo 需要的。
  • 我的意思是对于某些用户,第二个字符串会给出“Not a value”,第三个字符串会给出“3000.04”。对于其他人,第二个和第三个字符串都会给出“Not a value”。这取决于用户所在区域设置的分组和小数分隔符。
  • 当然,这就是为什么它适用于我的第二个字符串而不是第三个字符串。我根据我的机器配置设置了第三个字符串的分组和小数点分隔符不正确,因此@icekomo 可以看到由于输入字符串格式不正确而导致相同的数字失败。
  • 我更新了这个问题,为您提供了一个用户使用应用程序这一部分的示例。
猜你喜欢
  • 2023-01-12
  • 1970-01-01
  • 2017-02-25
  • 2021-04-17
  • 2017-01-29
  • 1970-01-01
  • 2012-07-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多