1

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

我正在非常努力地遵守“在处理货币时使用 NSDecimal”的格言,尽管我发现像许多其他发布问题的人一样很难做到这一点。我正在稳步前进,但是在我了解 NSDecimal 和 Format Specifications 之后,我确信这会看起来微不足道。

这是我正在使用的 IBAction(它由 Editing Changed 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

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

4

2 回答 2

1

如果您想保证文本值的小数点后有 2 位数字,您可以使用 NSNumberFormatter,如下面的代码(取自此处的答案):

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

我相信这应该保持 NSDecimalNumber 的精度。就个人而言,出于性能原因,我更喜欢使用 NSDecimal C 结构,但这有点难以将值输入和输出。

于 2010-01-03T04:41:38.247 回答
0

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

有关更多信息,请参阅:

于 2011-08-26T06:13:40.417 回答