NSNumberFormatter:dispatch_once 货币变化的地方
NSNumberFormatter: dispatch_once where Currency changes
我有一个表格视图,其中 NSDecimalNumber
的列表将以他们自己的货币显示。
我在 NSNumberFormatter
上使用 dispatch_once
但请注意,有时它会完全忽略我设置小数位数或小数位数后缀的命令。
目前我能够解决这个问题的唯一方法是初始化 NSNumberFormatter
每一行,这有点傻。
即:
- (NSNumberFormatter *)currencyFormatWithCurrency:(NSString *)currency
{
static NSNumberFormatter *_formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_formatter = [[NSNumberFormatter alloc] init];
});
[_formatter setCurrencyCode:currency];
[_formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[_formatter setMaximumFractionDigits:0];
[_formatter setGeneratesDecimalNumbers:NO];
[_formatter setRoundingMode:NSNumberFormatterRoundUp];
return _formatter;
}
// someCurrency is a string that will change per row
// someAmount is a NSDecimalNumber that will change per row
NSNumberFormatter *formatter = [self currencyFormatWithCurrency:someCurrency];
NSString *formattedAmount = [formatter stringFromNumber:someAmount];
self.amountLabel.text = formattedAmount;
有时,如果我输入 80000
这样的数字,它会 return 80,000.00
(有时取决于货币)。
我想我可以初始化 NSNumberFormatter
并在每一行上将其置零。
也许我做错了,但是否有办法确保我不需要继续创建 NSNumberFormatter
来确保它理解我给它的规则?
非常感谢
NSNumberFormatter 不是线程安全的。那会导致各种各样的问题。 (好吧,你使用它的方式并不是真正的线程安全,因为你可能在一个线程中修改它,而另一个线程正在使用它,但是仅从两个线程使用 NSNumberFormatter 是不安全的)。
你总是可以用
这样的方法做一些事情
NSString* lastCurrency = nil;
NSNumberFormatter* formatter = nil;
for (;;) {
...
NSString* currency = ...;
if (! [lastCurrency isEqualToString:currency]) {
lastCurrency = currency;
formatter = ...;
}
}
如果在大多数情况下货币不变,则效果很好。
我认为这是我从以下内容中得到的一个可能的解决方案 website 可能会有所帮助。
NSString *HTCurrencyString(double amount, NSString *currencyCode)
{
static NSString *currencyFormatterKey = @"HTCurrencyFormatter";
NSNumberFormatter *currencyFormatter = [[NSThread currentThread] threadDictionary][currencyFormatterKey];
if (currencyFormatter == nil)
{
currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setLocale:[NSLocale currentLocale]];
[[NSThread currentThread] threadDictionary][currencyFormatterKey] = currencyFormatter;
}
[currencyFormatter setCurrencyCode:currencyCode];
[currencyFormatter setMaximumFractionDigits:0];
[currencyFormatter setRoundingMode:NSNumberFormatterRoundHalfUp];
return [currencyFormatter stringFromNumber:@(amount)];
}
我有一个表格视图,其中 NSDecimalNumber
的列表将以他们自己的货币显示。
我在 NSNumberFormatter
上使用 dispatch_once
但请注意,有时它会完全忽略我设置小数位数或小数位数后缀的命令。
目前我能够解决这个问题的唯一方法是初始化 NSNumberFormatter
每一行,这有点傻。
即:
- (NSNumberFormatter *)currencyFormatWithCurrency:(NSString *)currency
{
static NSNumberFormatter *_formatter = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_formatter = [[NSNumberFormatter alloc] init];
});
[_formatter setCurrencyCode:currency];
[_formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[_formatter setMaximumFractionDigits:0];
[_formatter setGeneratesDecimalNumbers:NO];
[_formatter setRoundingMode:NSNumberFormatterRoundUp];
return _formatter;
}
// someCurrency is a string that will change per row
// someAmount is a NSDecimalNumber that will change per row
NSNumberFormatter *formatter = [self currencyFormatWithCurrency:someCurrency];
NSString *formattedAmount = [formatter stringFromNumber:someAmount];
self.amountLabel.text = formattedAmount;
有时,如果我输入 80000
这样的数字,它会 return 80,000.00
(有时取决于货币)。
我想我可以初始化 NSNumberFormatter
并在每一行上将其置零。
也许我做错了,但是否有办法确保我不需要继续创建 NSNumberFormatter
来确保它理解我给它的规则?
非常感谢
NSNumberFormatter 不是线程安全的。那会导致各种各样的问题。 (好吧,你使用它的方式并不是真正的线程安全,因为你可能在一个线程中修改它,而另一个线程正在使用它,但是仅从两个线程使用 NSNumberFormatter 是不安全的)。
你总是可以用
这样的方法做一些事情NSString* lastCurrency = nil;
NSNumberFormatter* formatter = nil;
for (;;) {
...
NSString* currency = ...;
if (! [lastCurrency isEqualToString:currency]) {
lastCurrency = currency;
formatter = ...;
}
}
如果在大多数情况下货币不变,则效果很好。
我认为这是我从以下内容中得到的一个可能的解决方案 website 可能会有所帮助。
NSString *HTCurrencyString(double amount, NSString *currencyCode)
{
static NSString *currencyFormatterKey = @"HTCurrencyFormatter";
NSNumberFormatter *currencyFormatter = [[NSThread currentThread] threadDictionary][currencyFormatterKey];
if (currencyFormatter == nil)
{
currencyFormatter = [[NSNumberFormatter alloc] init];
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[currencyFormatter setLocale:[NSLocale currentLocale]];
[[NSThread currentThread] threadDictionary][currencyFormatterKey] = currencyFormatter;
}
[currencyFormatter setCurrencyCode:currencyCode];
[currencyFormatter setMaximumFractionDigits:0];
[currencyFormatter setRoundingMode:NSNumberFormatterRoundHalfUp];
return [currencyFormatter stringFromNumber:@(amount)];
}