在更改事件上将货币格式重新应用于UITextField [英] Re-Apply currency formatting to a UITextField on a change event

查看:130
本文介绍了在更改事件上将货币格式重新应用于UITextField的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用包含本地化货币值的UITextField。我已经看过很多关于如何使用它的帖子,但我的问题是:如何在每次按键后将货币格式重新应用到UITextField?

I'm working with a UITextField that holds a localized currency value. I've seen lots of posts on how to work with this, but my question is: how do I re-apply currency formatting to the UITextField after every key press?

我知道我可以设置和使用货币格式化程序:

I know that I can set up and use a currency formatter with:

NSNumberFormatter *currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
...
[currencyFormatter stringFromNumber:...];

但我不知道如何挂钩。

例如,如果字段中的值显示为$ 12,345并且用户点击6键,则该值应更改为$ 123,456。

For instance, if the value in the field reads "$12,345" and the user taps the "6" key, then the value should change to "$123,456".

哪个回调是正确的回复(我应该使用 textField:shouldChangeCharactersInRange:replacementString:还是自定义目标动作)我该怎么做使用NSNumberFormatter解析并重新应用格式到UITextField的文本属性?

Which callback is the "correct" one to do this in (should I use textField:shouldChangeCharactersInRange:replacementString: or a custom target-action) and how do I use the NSNumberFormatter to parse and re-apply formatting to the UITextField's text property?

任何帮助将不胜感激!谢谢!

Any help would be much appreciated! Thanks!

推荐答案

我一直在研究这个问题,我想我找到了一个很好的,干净的解决方案。我将向您展示如何正确更新用户输入的文本字段,但您必须自己弄清楚本地化,无论如何该部分应该很容易。

I've been working on this issue and I think I figured out a nice, clean solution. I'll show you how to appropriately update the textfield on user input, but you'll have to figure out the localization yourself, that part should be easy enough anyway.

- (void)viewDidLoad
{
    [super viewDidLoad];


    // setup text field ...

#define PADDING 10.0f

    const CGRect bounds = self.view.bounds;
    CGFloat width       = bounds.size.width - (PADDING * 2);
    CGFloat height      = 30.0f;
    CGRect frame        = CGRectMake(PADDING, PADDING, width, height);

    self.textField                      = [[UITextField alloc] initWithFrame:frame];
    _textField.backgroundColor          = [UIColor whiteColor];
    _textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    _textField.autocapitalizationType   = UITextAutocapitalizationTypeNone;
    _textField.autocorrectionType       = UITextAutocorrectionTypeNo;
    _textField.text                     = @"0";
    _textField.delegate                 = self;
    [self.view addSubview:_textField];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];


    // force update for text field, so the initial '0' will be formatted as currency ...

    [self textField:_textField shouldChangeCharactersInRange:NSMakeRange(0, 0) replacementString:@"0"];
}

- (void)viewDidUnload
{
    self.textField = nil;

    [super viewDidUnload];
}

这是 UITextFieldDelegate 方法中的代码 textField:shouldChangeCharactersInRange:replacementString:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    NSString *text             = _textField.text;
    NSString *decimalSeperator = @".";
    NSCharacterSet *charSet    = nil;
    NSString *numberChars      = @"0123456789";


    // the number formatter will only be instantiated once ...

    static NSNumberFormatter *numberFormatter;
    if (!numberFormatter)
    {
        numberFormatter = [[NSNumberFormatter alloc] init];
        numberFormatter.numberStyle           = NSNumberFormatterCurrencyStyle;
        numberFormatter.maximumFractionDigits = 10;
        numberFormatter.minimumFractionDigits = 0;
        numberFormatter.decimalSeparator      = decimalSeperator;
        numberFormatter.usesGroupingSeparator = NO;
    }


    // create a character set of valid chars (numbers and optionally a decimal sign) ...

    NSRange decimalRange = [text rangeOfString:decimalSeperator];
    BOOL isDecimalNumber = (decimalRange.location != NSNotFound);
    if (isDecimalNumber)
    {
        charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];        
    }
    else
    {
        numberChars = [numberChars stringByAppendingString:decimalSeperator];
        charSet = [NSCharacterSet characterSetWithCharactersInString:numberChars];
    }


    // remove amy characters from the string that are not a number or decimal sign ...

    NSCharacterSet *invertedCharSet = [charSet invertedSet];
    NSString *trimmedString = [string stringByTrimmingCharactersInSet:invertedCharSet];
    text = [text stringByReplacingCharactersInRange:range withString:trimmedString];


    // whenever a decimalSeperator is entered, we'll just update the textField.
    // whenever other chars are entered, we'll calculate the new number and update the textField accordingly.

    if ([string isEqualToString:decimalSeperator] == YES) 
    {
        textField.text = text;
    }
    else 
    {
        NSNumber *number = [numberFormatter numberFromString:text];
        if (number == nil) 
        {
            number = [NSNumber numberWithInt:0];   
        }
        textField.text = isDecimalNumber ? text : [numberFormatter stringFromNumber:number];
    }

    return NO; // we return NO because we have manually edited the textField contents.
}

编辑1:修复内存泄漏。

编辑2:为Umka更新 - 在小数点分隔符后处理 0 。代码也针对ARC更新。

Edit 2: updated for Umka - handling of 0 after decimal separator. Code is updated for ARC as well.

这篇关于在更改事件上将货币格式重新应用于UITextField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆