如何在NSNumberFormatter的输出上强制使用符号字符

时间:2013-01-04 01:09:51

标签: objective-c ios nsnumberformatter

我想使用数字格式化程序来生成输出,因此该数字会自动为用户的语言环境设置格式,但我希望它能像“%+。1f”一样在 printf(),总是指定一个符号。

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.maximumFractionDigits = 1;

double val = 3.1234;
label.text = [NSString stringWithFormat: @"XXX %@ XXX", [nf stringFromNumber: [NSNumber numberWithDouble: val]]];

我希望标签在美国出现“XXX +3.1 XXX”,并且在任何其他位置都是相应的但等效的字符串。我能找到的唯一内容是setPositiveFormat:setPositivePrefix:

但我想要设置格式,因为我不知道如何格式化其他国家/地区的数字;我不知道是否使用加号来指定阿拉伯语或俄语中的正数或某些我没有想到的文化。我知道,例如,小数点,逗号,空格等在欧洲国家与美国相比都有不同的含义 - 对于+/-符号也是如此吗?

我目前所做的是:

label.text = [NSString stringWithFormat: @"XXX %s%@ XXX", (val < 0) ? "" : "+",
    [nf stringFromNumber: [NSNumber numberWithDouble: val]]];

但是这假定'+'和' - '对所有格式都是正确的。

我确信它必须存在,因为它是 printf()中的标准格式化事物,因为黑暗时代......

6 个答案:

答案 0 :(得分:15)

这个怎么样:

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.maximumFractionDigits = 1;

double val = 3.1234;
NSString *sign = (val < 0) ? [nf minusSign] : [nf plusSign];
NSString *num = [nf stringFromNumber:@(abs(val))]; // avoid double negative
label.text = [NSString stringWithFormat: @"XXX %@%@ XXX", sign, num];

您可能需要检查num是否具有sign前缀,以便它不会显示两次。

编辑:经过一些游戏后,已经确定,对于“十进制”样式,当前区域设置不使用positivePrefix。当前区域设置不使用标准plusSign字符以外的+。当前区域设置不使用与negativePrefix不同的minusSign。当前的区域设置不使用positiveSuffixnegativeSuffix

这样做更容易:

NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.maximumFractionDigits = 1;
[nf setPositivePrefix:[nf plusSign]];
[nf setNegativePrefix:[nf minusSign]];

label.text = [nf stringFromNumber:@(val)];

答案 1 :(得分:6)

这种情况很简单,只需添加前缀:

nf.positivePrefix= nf.plusSign;

答案 2 :(得分:3)

虽然它不会使用用户的区域设置,但您可以执行以下操作来生成+/-符号而不会产生NSNumberFormatter的昂贵开销:

// assume 'number' is an NSNumber
label.text = [NSString stringWithFormat:@"%+.02f", [number floatValue]];

答案 3 :(得分:0)

NSNumberFormatter的{​​{3}}没有针对您要执行的操作的任何规定 - 它允许您在指数上指定本地化的正号,但不是整个格式化的字符串。 underlying formatting language也没有本地化的正号。

除了制作一个包含指数的虚拟字符串,拉出本地化的正面符号,然后手动将最终格式化的字符串放在一起,我觉得你运气不好。

答案 4 :(得分:0)

swift中可重用的格式化程序:

var numberFormatter: NSNumberFormatter {
    let formatter = NSNumberFormatter()
    formatter.numberStyle = .DecimalStyle
    formatter.locale = NSLocale(localeIdentifier: "it_IT")//your Locale
    formatter.maximumFractionDigits = 2
    formatter.minimumFractionDigits = 0
    formatter.positivePrefix = formatter.plusSign
    return formatter
}

然后使用它:

let myDoubleValue = 12.00
let myStringNumber = numberFormatter.stringFromNumber(myDoubleValue)!

答案 5 :(得分:0)

简单案例

    let f = NumberFormatter()
    f.numberStyle = .currency
    f.positivePrefix = f.plusSign + f.currencySymbol

货币案例:

需要

Hack,因为只将前缀设置为plusSign将删除货币符号。

    let f = NumberFormatter()
    f.numberStyle = .currency
    f.positivePrefix = f.plusSign + f.currencySymbol

根据区域设置还有一些工作..货币符号可能在之前或之后,但这可能是另一个主题..

修改

即使它是另一个主题,我也说上面问题的可能解决方案是子类化NSNumberFormatter:

override func string(from number: NSNumber) -> String? {
    returns ( number.doubleValue >= 0 ? super.plusSign : "" ) + super.string(from: number)
}

这样,NSNumberFormatter应该管理货币位置,而子类只是在前面添加+符号。没有时间对此进行深入测试,但至少这是一种方法。