iPhone货币输入使用NSDecimal而不是float

时间:2010-01-03 03:11:51

标签: iphone cocoa-touch keyboard decimal nsdecimalnumber

iPhone / Objective-C / Cocoa新手在这里。根据stackoverflow上的一些帖子,我拼凑了一个IBAction,我正在使用我正在构建的基本iPhone计算器应用程序。 IBAction与数字键盘一起使用,允许输入十进制数而无需输入小数点。

我正在努力坚持“在处理货币时使用NSDecimal”格言,尽管我发现很难像许多其他人一样发布问题。我正在取得稳步进展,但是在我深入了解NSDecimal和格式规范之后,我肯定会看起来很琐碎。

这是我正在使用的IBAction(由编辑更改的UITextField事件触发):

// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
 static BOOL toggle = YES; // was this method triggered by the user?

 // the user touched the keypad
 if (toggle)
 {
  toggle = NO;

  // retrieve the strings in input fields
  NSString *currencyField1Text = currencyField1.text;
  NSString *currencyField2Text = currencyField2.text;

  if (sender == currencyField1) {
   currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   float currency = [currencyFieldText floatValue]/100; 
   currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];
  }
  else if (sender == currencyField2) {
   currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];
  }
  else  {
   NSLog(@"Some unexpected input");   
  }  
 }
 else 
 {
  toggle = YES;
 }

} // end method calculateResults

currencyField1代码段使用浮点数,currencyField2段使用NSDecimal。

currencyField1段按预期工作:显示小数点后两位数的所有数字(即使删除键用于删除所有输入的数字);但是,它在处理大货币值时遇到并完全说明了使用浮点数的问题:当输入的数字超过8位数时,会出现舍入错误。

currencyField2段通过使用NSDecimal而不是float来避免舍入错误问题;但它并不总是显示小数点后两位数的数字 - 当删除键用于删除所有输入的数字时显示。我认为这个问题源于这行代码:

currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];

这是以下行的推论,它为浮点数生成所需的格式:

currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];

所以,我认为我需要相当于@“%0.2f”来格式化“0”值NSDecimalNumber的显示。我已经这么多个小时了,我很尴尬,但我无法理解。

任何帮助或指示表示赞赏。

编辑:我合并了NSNumberFormatter对象(类似于布拉德在他的评论中所描述的),似乎已经解决了这个问题。但是,我希望有一些关于重构代码的反馈,因为我已经有了它的工作。这是修改后的代码:

// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
 static BOOL toggle = YES; // was this method triggered by the user?

 // the user touched the keypad
 if (toggle)
 {
  toggle = NO;

  // retrieve the strings in input fields
  NSString *currencyField1Text = currencyField1.text;
  NSString *currencyField2Text = currencyField2.text;

  // new code elements
  NSNumberFormatter * nf = [[[NSNumberFormatter alloc] init]autorelease];
  [nf setNumberStyle:NSNumberFormatterCurrencyStyle];
  [nf setCurrencySymbol:@""];
  [nf setCurrencyGroupingSeparator:@""];

  if (sender == currencyField1) {
   currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency = [[NSDecimalNumber decimalNumberWithString:currencyField1Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField1.text = [nf stringFromNumber:currency];  
  }
  else if (sender == currencyField2) {
   currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
   NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]]; 
   currencyField2.text = [nf stringFromNumber:currency2];
  }
  else  {
   NSLog(@"Some unexpected input");   
  }  
 }
 else 
 {
  toggle = YES;
 }

} // end method calculateResults

它解决了我最初的问题,但我很感激有关如何改进它的任何建议。感谢。

2 个答案:

答案 0 :(得分:1)

如果要保证文本值小数点后2位数,可以使用NSNumberFormatter,如下面的代码所示(从答案here中提取):

NSNumberFormatter *decimalNumberFormatter = [[NSNumberFormatter alloc] init];
[decimalNumberFormatter setMinimumFractionDigits:2];
[decimalNumberFormatter setMaximumFractionDigits:2];
currencyField2.text = [decimalNumberFormatter stringFromNumber:currency2];
[decimalNumberFormatter release];

我认为这应该保留NSDecimalNumber的精度。就个人而言,出于性能原因,我更倾向于使用NSDecimal C结构,但是进入和退出值更难。

答案 1 :(得分:0)

你不能使用-setFormat:方法(NSNumberFormatter)代替NSNumberFormatter吗?似乎应该能够为您的目的配置它,并且您不必处理货币格式化字符串上的奇怪“黑客”。

有关详细信息,请参阅: