iPhone / Objective-C / Cocoa新手在这里。根据stackoverflow上的一些帖子,我拼凑了一个IBAction,我正在使用我正在构建的基本iPhone计算器应用程序。 IBAction与数字键盘一起使用,允许输入十进制数而无需输入小数点。
我正在努力坚持“在处理货币时使用NSDecimal”格言,尽管我发现很难像许多其他人一样发布问题。我正在取得稳步进展,但是在我深入了解NSDecimal和格式规范之后,我肯定会看起来很琐碎。
这是我正在使用的IBAction(由编辑更改的UITextField事件触发):
// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
static BOOL toggle = YES; // was this method triggered by the user?
// the user touched the keypad
if (toggle)
{
toggle = NO;
// retrieve the strings in input fields
NSString *currencyField1Text = currencyField1.text;
NSString *currencyField2Text = currencyField2.text;
if (sender == currencyField1) {
currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
float currency = [currencyFieldText floatValue]/100;
currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];
}
else if (sender == currencyField2) {
currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];
}
else {
NSLog(@"Some unexpected input");
}
}
else
{
toggle = YES;
}
} // end method calculateResults
currencyField1代码段使用浮点数,currencyField2段使用NSDecimal。
currencyField1段按预期工作:显示小数点后两位数的所有数字(即使删除键用于删除所有输入的数字);但是,它在处理大货币值时遇到并完全说明了使用浮点数的问题:当输入的数字超过8位数时,会出现舍入错误。
currencyField2段通过使用NSDecimal而不是float来避免舍入错误问题;但它并不总是显示小数点后两位数的数字 - 当删除键用于删除所有输入的数字时显示。我认为这个问题源于这行代码:
currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];
这是以下行的推论,它为浮点数生成所需的格式:
currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];
所以,我认为我需要相当于@“%0.2f”来格式化“0”值NSDecimalNumber的显示。我已经这么多个小时了,我很尴尬,但我无法理解。
任何帮助或指示表示赞赏。
编辑:我合并了NSNumberFormatter对象(类似于布拉德在他的评论中所描述的),似乎已经解决了这个问题。但是,我希望有一些关于重构代码的反馈,因为我已经有了它的工作。这是修改后的代码:// called when user touches a key or button
- (IBAction)processKeystrokes:(id)sender
{
static BOOL toggle = YES; // was this method triggered by the user?
// the user touched the keypad
if (toggle)
{
toggle = NO;
// retrieve the strings in input fields
NSString *currencyField1Text = currencyField1.text;
NSString *currencyField2Text = currencyField2.text;
// new code elements
NSNumberFormatter * nf = [[[NSNumberFormatter alloc] init]autorelease];
[nf setNumberStyle:NSNumberFormatterCurrencyStyle];
[nf setCurrencySymbol:@""];
[nf setCurrencyGroupingSeparator:@""];
if (sender == currencyField1) {
currencyField1Text = [currencyField1Text stringByReplacingOccurrencesOfString:@"." withString:@""];
NSDecimalNumber *currency = [[NSDecimalNumber decimalNumberWithString:currencyField1Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
currencyField1.text = [nf stringFromNumber:currency];
}
else if (sender == currencyField2) {
currencyField2Text = [currencyField2Text stringByReplacingOccurrencesOfString:@"." withString:@""];
NSDecimalNumber *currency2 = [[NSDecimalNumber decimalNumberWithString:currencyField2Text] decimalNumberByDividingBy:[NSDecimalNumber decimalNumberWithString:@"100"]];
currencyField2.text = [nf stringFromNumber:currency2];
}
else {
NSLog(@"Some unexpected input");
}
}
else
{
toggle = YES;
}
} // end method calculateResults
它解决了我最初的问题,但我很感激有关如何改进它的任何建议。感谢。
答案 0 :(得分:1)
如果要保证文本值小数点后2位数,可以使用NSNumberFormatter,如下面的代码所示(从答案here中提取):
NSNumberFormatter *decimalNumberFormatter = [[NSNumberFormatter alloc] init];
[decimalNumberFormatter setMinimumFractionDigits:2];
[decimalNumberFormatter setMaximumFractionDigits:2];
currencyField2.text = [decimalNumberFormatter stringFromNumber:currency2];
[decimalNumberFormatter release];
我认为这应该保留NSDecimalNumber的精度。就个人而言,出于性能原因,我更倾向于使用NSDecimal C结构,但是进入和退出值更难。
答案 1 :(得分:0)
你不能使用-setFormat:
方法(NSNumberFormatter)代替NSNumberFormatter吗?似乎应该能够为您的目的配置它,并且您不必处理货币格式化字符串上的奇怪“黑客”。
有关详细信息,请参阅: