iPhone/Objective-C/Cocoa newbie ici. Basé sur un certain nombre de messages sur stackoverflow, j'ai bricolé ensemble un IBAction que j'utilise dans une application de calculatrice iPhone de base que je construis. IBAction fonctionne avec le pavé numérique pour permettre la saisie de nombres décimaux sans avoir à entrer un point décimal. J'essaie très fort d'adhérer à l'adage «utiliser NSDecimal en matière de devise» bien que je trouve difficile de le faire comme tant d'autres personnes qui ont posté des questions. Je fais des progrès constants, mais j'ai frappé un mur qui, j'en suis sûr, semblera anodin après que j'ai pris connaissance de la NSDecimal et des spécifications de format.iPhone saisie de la monnaie en utilisant NSDecimal au lieu de float
Voici le IBAction J'utilise (il est déclenché par édition changé UITextField Event):
// 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
Le segment de code currencyField1 utilise des flotteurs, le segment currencyField2 utilise NSDecimal. Le segment currencyField1 fonctionne comme vous le souhaitez: affiche tous les chiffres avec deux chiffres après le point décimal (même lorsque la touche de suppression est utilisée pour supprimer tous les chiffres entrés); cependant, il souffre et illustre parfaitement le problème de l'utilisation des flottants lorsqu'il s'agit de valeurs de devises importantes: des erreurs d'arrondi apparaissent lorsque les chiffres saisis dépassent 8 chiffres.
Le segment currencyField2 évite les problèmes d'arrondi en utilisant NSDecimal au lieu de float; Cependant, il n'affiche pas toujours les chiffres avec deux chiffres après la virgule décimale - cela est affiché lorsque la touche de suppression est utilisée pour supprimer tous les chiffres entrés. Je crois que le problème est dû à cette ligne de code:
currencyField2.text = [@"" stringByAppendingFormat:@"%@", currency2];
Ceci est le corollaire de la ligne suivante qui produit le format souhaité pour les flotteurs:
currencyField1.text = [@"" stringByAppendingFormat:@"%0.2f", currency];
Donc, je pense que je dois l'équivalent de @ "% 0.2f" pour formater l'affichage d'une valeur "0" NSDecimalNumber. Cela fait tellement d'heures que je suis gêné, mais je n'arrive pas à comprendre.
Toute aide ou pointeur sont appréciés.
EDIT: J'ai incorporé l'objet NSNumberFormatter (similaire à ce que Brad décrit dans son commentaire) qui semble avoir résolu le problème. Cependant, j'aimerais avoir des commentaires sur la refactorisation du code maintenant que je l'ai fonctionné. Voici le code révisé:
// 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
Il résout mon problème initial, mais j'apprécierais des conseils sur la façon de l'améliorer. Merci.
Merci Brad. Votre suggestion a fonctionné, mais le «0» principal serait perdu si l'utilisateur a supprimé tous les chiffres entrés. Cela donnerait une valeur affichée de ".00" où je voulais "0.00". J'ai corrigé cela avec "[nf setNumberStyle: NSNumberFormatterCurrencyStyle];" qui a apporté les points décimaux et deux chiffres de fuite; mais aussi le symbole monétaire ("$") et le séparateur de groupe monétaire (",") que j'ai éliminé en utilisant "[nf setCurrencySymbol: @" "];" et "[nf setCurrencyGroupingSeparator: @" "];" respectivement. Merci pour le pointeur - NSNumberFormatter a résolu le problème! –