【问题标题】:Rounding currency values (SwiftUI, Core Data)四舍五入货币值(SwiftUI、Core Data)
【发布时间】:2020-07-17 14:05:10
【问题描述】:

我正在尝试在 SwiftUI 中创建一个简单的 TextField,它将提供的值格式化为货币的有效值。我需要将值四舍五入为 2 位数。并使用 Core Data 存储四舍五入的值(我知道该怎么做,我使用的是 Decimal 类型,顺便说一句)。

到目前为止,我有这个:

import SwiftUI

struct ContentView: View {
    @State private var newValueAsString = ""
    @State private var value: NSDecimalNumber = 0
    
    let decimalBehavior = NSDecimalNumberHandler(roundingMode: .plain, scale: 2, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: true)
    
    var body: some View {
        VStack {
            TextField("0", text: $newValueAsString, onCommit: {
                self.value = NSDecimalNumber(string: self.newValueAsString).rounding(accordingToBehavior: self.decimalBehavior)
                print("\(self.value)")
            }
            )
                .multilineTextAlignment(.trailing)
                .font(Font.system(size: 30))
                .keyboardType(.decimalPad)
            
            // Just to test. Later I will save the value to Core Data.
            Text("\(self.value)")
        }
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

问题

当 iOS 区域使用逗号而不是点(例如,波兰)时,它无法正常工作。十进制键盘有“,”而不是“。”当我使用“,”时,数字没有正确四舍五入。 123,456 变为 123。而使用点的区域(例如,美国)123.456 变为 123.46,如预期的那样。

我在这里缺少什么?我的猜测是 NumberFormatter,但我无法让它工作。

【问题讨论】:

  • 请注意,它是。只存储 2 位数的汇率是个坏主意,以日元为例,例如 0.008 欧元或 0.009 美元
  • 哦,感谢您指出这一点。所以我应该根据货币四舍五入吗?我需要研究如何去做。

标签: ios swift core-data swiftui currency


【解决方案1】:

NSDecimalNumber 可以使用字符串和语言环境进行初始化。 The documentation 明确提到语言环境用于解释小数分隔符(强调我的):

locale:定义用于解释 numericString 中数字的语言环境(特别是 decimalSeparator)的字典 (!)。

所以你可以这样做:

// Here I am passing the current Locale but you should pass whatever makes sense to your input
self.value = NSDecimalNumber(string: self.newValueAsString, locale: Locale.current).rounding(accordingToBehavior: self.decimalBehavior)

例子:

print(NSDecimalNumber(string: "100.50", locale: Locale(identifier: "en_US"))) // => 100.5
print(NSDecimalNumber(string: "100,50", locale: Locale(identifier: "el_GR"))) // => 100.5

【讨论】:

  • 非常感谢!它有效,Locale.current 对我的目的来说是非常好的解决方案。一个问题,不过。是否有可能使它与两者一起使用。并且,同时?我的意思是我们只能在 decimalPad 上使用其中一个,但是如果当 region 在软件键盘上使用 dot 时,有人会使用物理键盘编写 comm 怎么办?
  • @mallow 我认为没有 API 可以自动为您处理这个问题(但我可能错了!)。在这种情况下,可能需要手动验证(例如在插入或粘贴文本时会发生什么)。
  • 是的,插入文本是对的。它在某种程度上起作用。例如,123a 将返回 123。但 a123 将返回 NaN。我需要进一步调查。但是已经少了一个需要解决的问题。谢谢! :)
猜你喜欢
  • 1970-01-01
  • 2011-09-10
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 2011-10-01
  • 2018-02-14
  • 2020-04-08
  • 2021-05-23
相关资源
最近更新 更多