6

我正在尝试做一些我认为相当简单的事情:让用户输入一个美元金额,将该金额存储在一个 NSNumber(NSDecimalNumber?)中,然后在稍后再次显示该金额格式化为货币。

我的麻烦不在于 setNumberStyle:NSNumberFormatterCurrencyStyle 并将浮点数显示为货币。问题更多在于所说的 numberFormatter 如何与这个 UITextField 一起工作。我可以找到几个例子。11 月的这个帖子这个帖子给了我一些想法,但给我留下了更多问题。

我正在使用 UIKeyboardTypeNumberPad 键盘并了解我可能应该在显示时在字段中显示 $0.00(或任何本地货币格式),然后当用户输入数字以移动小数位时:

  • 从显示 $0.00 开始
  • 点击 2 键:显示 $0.02
  • 点击 5 键:显示 $0.25
  • 点击 4 键:显示 $2.54
  • 点击 3 键:显示 $25.43

然后 [numberFormatter numberFromString:textField.text] 应该给我一个可以存储在我的 NSNumber 变量中的值。

可悲的是我仍在挣扎:这真的是最好/最简单的方法吗?如果是这样,那么也许有人可以帮助我实施?我觉得 UITextField 可能需要一个代表来响应每个按键,但不确定是什么,在哪里以及如何实现它?!任何示例代码?我将不胜感激!我从高处和低处搜索...

Edit1:所以我正在研究 NSFormatter 的stringForObjectValue:以及我能找到的最接近 benzado 推荐的东西:UITextViewTextDidChangeNotification。很难在其中任何一个上找到示例代码......所以如果你知道在哪里看,请告诉我?

4

7 回答 7

10

我的解决方案:


- (BOOL)textField:(UITextField *)textField
    shouldChangeCharactersInRange:(NSRange)range 
    replacementString:(NSString *)string
{
  // Clear all characters that are not numbers
  // (like currency symbols or dividers)
  NSString *cleanCentString = [[textField.text
    componentsSeparatedByCharactersInSet:
    [[NSCharacterSet decimalDigitCharacterSet] invertedSet]]
      componentsJoinedByString:@""];
  // Parse final integer value
  NSInteger centAmount = cleanCentString.integerValue;
  // Check the user input
  if (string.length > 0)
  {
    // Digit added
    centAmount = centAmount * 10 + string.integerValue;
  }
  else
  {
    // Digit deleted
    centAmount = centAmount / 10;
  }
  // Update call amount value
  [_amount release];
  _amount = [[NSNumber alloc] initWithFloat:(float)centAmount / 100.0f];
  // Write amount with currency symbols to the textfield
  NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
  [_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
  [_currencyFormatter setCurrencyCode:@"USD"];
  [_currencyFormatter setNegativeFormat:@"-¤#,##0.00"];
  textField.text = [_currencyFormatter stringFromNumber:_amount];
  [_currencyFormatter release]
  // Since we already wrote our changes to the textfield
  // we don't want to change the textfield again
  return NO;
}

于 2010-05-29T15:57:34.477 回答
3

如果我现在必须写,这是我会使用的粗略攻击计划。诀窍是在隐藏的 UITextField 中键入内容,并在用户键入时使用格式化值更新 UILabel。

  1. 创建一个 UITextField,将其隐藏,为其分配一个委托,然后使其成为召唤键盘的第一响应者。
  2. 在您的委托中,通过获取文本字段的新值并将其转换为数字来响应 textDidChange: 消息(懒得查找确切名称)。确保空字符串转换为零。
  3. 通过您的格式化程序运行该数字,并使用该格式化货币值更新 UILabel。

每次按键时,标签都会更新,因此用户会感觉好像她正在编辑格式化的值,而实际上她正在编辑隐藏的文本字段。多么狡猾!

于 2009-02-27T06:03:22.887 回答
1

好吧,我认为这更好:

- (void)viewWillDisappear:(BOOL)animated{ [[NSNotificationCenter defaultCenter] removeObserver:self  name:UITextFieldTextDidChangeNotification object:nil]; }

-(void)viewDidAppear:(BOOL)animated{
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChanged:) name:UITextFieldTextDidChangeNotification object:nil];
}

-(void)textDidChanged:(NSNotification *)notification{
 [[NSNotificationCenter defaultCenter] removeObserver:self  name:UITextFieldTextDidChangeNotification object:nil];
 UITextField * textField= [notification object];
 NSString * sinPesos= [textField.text stringByReplacingOccurrencesOfString:@"$" withString:@""];
 NSString * sinPuntos= [sinPesos stringByReplacingOccurrencesOfString:@"." withString:@""];

 float monto = [sinPuntos floatValue]; 

 monto= monto/100;

 NSString * cardText= [[self montoFormatter] stringFromNumber:[NSNumber numberWithDouble:monto]]; 

 textField.text = ([cardText isEqualToString: @"0"] ? @"":cardText);
 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textDidChanged:) name:UITextFieldTextDidChangeNotification object:nil];
} 

-(NSNumberFormatter *)montoFormatter{
 NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
 [numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
 [numberFormatter setMaximumFractionDigits:2];
 return [numberFormatter autorelease];
}

试试看 :)

于 2010-04-21T16:17:36.607 回答
1

由于我很懒惰,而且我不能忍受即时重新格式化我的输入“以帮助我”,我说:

让他们输入一个十进制数。当他们离开现场时,重新格式化。

于 2011-09-08T14:00:19.417 回答
0

好吧,这有点晚了,但我想我还是会试一试。这可能更像是一种解决方法,并且可能是混乱的代码,但它对我有用。我在 IB 中连接了一个标签和一个隐藏的文本字段,并使用 UITextFieldDelegate 委托编写了这段代码。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
    if (textField == fineHiddenTextField) {
        NSString *fineText = [textField.text stringByReplacingCharactersInRange:range withString:string];
        if ([fineText length] == 0) {
            NSString *emptyFine = @"0.00";
            float fineValue = [emptyFine floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else if ([fineText length] == 1) {
            NSString *firstDec = [NSString stringWithFormat:@"0.0%@", fineText];
            float fineValue = [firstDec floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else if ([fineText length] == 2) {
            NSString *secondDec = [NSString stringWithFormat:@"0.%@", fineText];
            float fineValue = [secondDec floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        } else {
            int decimalPlace = [fineText length] - 2;
            NSString *fineDollarAmt = [fineText substringToIndex:decimalPlace];
            NSString *fineCentsAmt = [fineText substringFromIndex:decimalPlace];
            NSString *finalFineValue = [NSString stringWithFormat:@"%@.%@", fineDollarAmt, fineCentsAmt];
            float fineValue = [finalFineValue floatValue];
            fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        }


        //fineEntryLabel.text = [NSString stringWithFormat:@"%.2f", fineValue];
        return YES;
    }
}

不完全是最整洁的,但它确实完成了工作。最初的 if 语句只是为了确保这只发生在这个特定的 textField 上(因为在同一页面中有多个。)这段代码用于输入钱(支付的罚款金额),我想要它简单易用。只需将您的标签设置为从右侧对齐,它应该。

我现在对咖啡有点迷恋,但我会回答你可能有的任何问题。:)

于 2009-08-19T18:27:08.943 回答
0

这是我的解决方案!

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    float valorUnit = [textField.text floatValue];

    if( string.length > 0)
    {
        float incremento = [string floatValue];

        valorUnit = valorUnit * 10.f + (incremento/100.f);
        NSString* strVal = [NSString stringWithFormat:@"%f", valorUnit];

        if (valorUnit > 0.f && valorUnit < 10.f) {
            textField.text  = [strVal substringToIndex:3];
        }
        else if (valorUnit < 100.f && valorUnit >= 10.f)
        {
            textField.text  = [strVal substringToIndex:4];
        }
        else if (valorUnit >=100.f && valorUnit <1000.f)
        {
            textField.text  = [strVal substringToIndex:5];
        }
        else {
            return NO;
        }

    }
    else {
        valorUnit = (valorUnit/10.f);
        NSString* strVal = [NSString stringWithFormat:@"%f", valorUnit];
        if (valorUnit > 0.f && valorUnit < 10.f) {
            textField.text  = [strVal substringToIndex:5];
        }
        else if (valorUnit < 100.f && valorUnit >= 10.f)
        {
            textField.text  = [strVal substringToIndex:6];
        }
        else if (valorUnit >=100.f && valorUnit <1000.f)
        {
            textField.text  = [strVal substringToIndex:7];
        }
        else {
            return NO;
        }
    }

return YES;

}

于 2009-12-18T03:21:41.120 回答
0

我写了一个开源UITextField子类来处理这个问题,可以在这里找到:

https://github.com/TomSwift/TSCurrencyTextField

我采用的方法类似于 Lars Schneider 在他的流行回答中建议的方法。但是我的版本完全封装在一个可以在任何地方使用的可重用组件中,就像 UITextField 一样。如果您选择实现任何 UITextFieldDelegate 方法,则可以,但这不是必需的。

于 2013-10-31T17:31:29.403 回答