如何将货币字符串值设置为 UITextField,保留编码?

Posted

技术标签:

【中文标题】如何将货币字符串值设置为 UITextField,保留编码?【英文标题】:How do I set a currency string value to a UITextField, preserving encoding? 【发布时间】:2012-03-28 22:40:51 【问题描述】:

我正在开发一个应用程序,我希望根据当前的语言环境处理不同的货币格式。使用 NSNumberFormatter 我可以正确地将数字转换为字符串并返回而不会出现问题。

但是,如果我将字符串值放入 UITextField 并稍后将其取回,我将无法将字符串转换回数字,而是会得到 nil 值。

下面是解释问题的示例代码:

NSNumberFormatter *nf = [Utils currencyFormatter];
NSNumber *n = [NSNumber numberWithInt:10000];
NSString *s = [nf stringFromNumber:n];
NSLog(@"String value = %@", s);
UITextField *t = [[UITextField alloc] init];
// I put the string into the text field ...
t.text = s;

// ... and later I get the value back
s = t.text;
NSLog(@"Text field text = %@", s);
n = [nf numberFromString:s];
NSLog(@"Number value = %d", [n intValue]);

currencyFormatter 方法是这样定义的:

+ (NSNumberFormatter *)currencyFormatter

    static NSNumberFormatter *currencyFormatter;
    if (!currencyFormatter) 
        currencyFormatter  = [[NSNumberFormatter alloc] init];
        [currencyFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4];
        [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
        [currencyFormatter setLocale:[NSLocale currentLocale]];
        if ([currencyFormatter generatesDecimalNumbers] || [[currencyFormatter roundingIncrement] floatValue] < 1) 
            [currencyFormatter setGeneratesDecimalNumbers:YES];
            [currencyFormatter setRoundingIncrement:[NSNumber numberWithFloat:0.01]];   
        
    

    return currencyFormatter;

(内部 if 用于强制格式化程序始终舍入到最小的十进制数字,例如,即使是 CHF 值)。

我在控制台中得到的是这样的:

2012-03-29 00:35:38.490 myMutuo2[45396:fb03] String value = € 10.000,00
2012-03-29 00:35:38.494 myMutuo2[45396:fb03] Text field text = € 10.000,00
2012-03-29 00:35:38.497 myMutuo2[45396:fb03] Number value = 0

奇怪的是,第一行中1 之间的空格字符在控制台中通过一个半空中的点表示,而在第二行中这个点消失了。我相信这是一个与编码相关的问题。

谁能帮我解决这个问题? 谢谢!

编辑

我把我的测试代码改成这样:

NSNumberFormatter *nf = [Utils currencyFormatter];
NSNumber *n = [NSNumber numberWithInt:10000];
NSString *s = [nf stringFromNumber:n];
NSLog(@"String value = %@ (space code is %d)", s, [s characterAtIndex:1]);
UITextField *t = [[UITextField alloc] init];
t.text = s;
s = t.text;
NSLog(@"Text field text = %@ (space code is %d)", s, [s characterAtIndex:1]);
n = [nf numberFromString:s];
NSLog(@"Number value = %d", [n intValue]);

发现这个:

2012-03-29 02:29:43.402 myMutuo2[45993:fb03] String value = € 10.000,00 (space code is 160)
2012-03-29 02:29:43.405 myMutuo2[45993:fb03] Text field text = € 10.000,00 (space code is 32)
2012-03-29 02:29:43.409 myMutuo2[45993:fb03] Number value = 0

NSNumberFormatter 将空格写为不间断空格(ASCII 字符 160),然后UITextField 将该空格重新编码为简单空格(ASCII 字符 32)。这种行为的任何已知解决方法?也许我可以用非破坏空间替换空间但是......它适用于所有语言环境吗?

【问题讨论】:

它仅适用于您的货币区域设置。我检查了它并获得了与您所说的相同的空值。 第二次查看我的编辑答案。这可能会对您有所帮助。 【参考方案1】:

一种可能的解决方法:您可以尝试通过正则表达式模式仅解析数字值(和标点符号),并根据该数字创建货币值。如果您以这种方式进行操作,如果用户输入了另一个货币符号或其他不应该存在的符号,那么用户可能会更加原谅...

【讨论】:

我已经在以前版本的代码中这样做了。但是我得到了奇怪的错误、异常和崩溃,可能是一些奇怪的语言环境。我真的很想使用NSNumberFormatter 的魔力来摆脱对字符串的所有自定义处理,并在“受控”环境中工作,在该环境中,我使用相同的格式化程序对象对字符串/数字进行编码和解码。 顺便说一句...用户放入UITextField的内容实际上是通过调用NSNumberFormatterstringFromNumber:方法生成的,所以我一直都知道文本字段包含什么已正确格式化。无需添加更多逻辑来解释该值。 您可以保存用户输入的值以供以后使用吗?为什么需要重新转换文本字段内容? 因为“用户输入”的值是通过委托类中的textField:shouldChangeCharactersInRange:replacementString:方法写入UITextField的。此方法会自动将用户插入的字符转换为货币格式的字符串。该字符串被保存到文本字段的text 属性中用于显示目的,稍后我会从这里取回它...【参考方案2】:

我只能通过自定义类扩展 UITextField 来解决这个问题。在这个新类中,我放置了一个NSString 类型的新@property,其中存储了文本字段的“计算”字符串值。此字符串将永远不会被修改,并将保留文本字段内容的原始编码。

当您需要再次处理文本字段的原始未触及内容时,您必须引用此新属性,而不是引用 text 属性。

使用单独的字符串容器是避免这些奇怪的编码更改的唯一方法。

【讨论】:

以上是关于如何将货币字符串值设置为 UITextField,保留编码?的主要内容,如果未能解决你的问题,请参考以下文章

UITextfield 在 1 - 100 之间验证国家货币

当 UITextField 的“editingDidBegin”控件事件触发时,将 UITextField 的当前值设置为一个属性

尝试将 UITextField 格式化为像货币计算器一样仅用于 iOS 中的数字输入

如何在可重用的 tableView 单元格中更新 UITextfield 中的文本值,每个单元格中的值不同

如何将 uitextfield 字符范围限制为 10 位

设置值后如何在 UITextField 中移动光标