2010-08-24 18 views
20

Es scheint, dass NSNumberFormatter Euro (und wahrscheinlich andere) Währungszeichenfolgen in einem numerischen Typ nicht analysieren kann. Kann mir bitte jemand falsch beweisen?Verwenden von NSNumberFormatter, um einen Dezimalwert aus einer internationalen Währungszeichenfolge zu erhalten

Ich versuche, das folgende erhalten eine numerische Menge von einer Währung Zeichenfolge zu verwenden:

NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease]; 
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSNumber *currencyNumber = [currencyFormatter numberFromString:currencyString]; 

Dies funktioniert gut für die britischen und US-Währung beträgt. Es beschäftigt sich sogar mit $ und £ und Tausender Trennzeichen ohne Probleme.

Wenn ich es jedoch mit Euro-Währungsbeträgen verwende (mit dem Region-Format in der Einstellungen-App auf Frankreich oder Deutschland eingestellt), wird eine leere Zeichenfolge zurückgegeben. Alle folgenden Zeichenfolgen fehlschlagen:

12,34 € 
12,34 
12.345,67 € 
12.345,67 

Es ist erwähnenswert, dass diese Strings genau dem entsprechen, was aus der stringFromNumber Methode des NSNumberFormatter kommt, wenn das entsprechende Gebietsschema verwendet wird.

die Region Format nach Frankreich in den Einstellungen App einstellen, dann currencyNumber bis 12.34 im folgenden Code, ergibt currencyString Einstellung ‚34 € bis '12 gesetzt wird:

NSNumberFormatter *currencyFormatter = [[[NSNumberFormatter alloc] init] autorelease]; 
[currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSString *currencyString = [currencyFormatter stringFromNumber:currencyNumber]; 

Es wäre offensichtlich recht sein Es ist einfach, dieses Problem speziell für den Euro zu hacken, aber ich hoffe, diese App in so vielen Ländern wie möglich zu verkaufen, und ich denke, dass eine ähnliche Situation bei anderen Ländern auftreten wird.

Hat jemand eine Antwort?

TIA, Duncan

+0

Ich habe noch keine Lösung gefunden, also würde jede Eingabe sehr geschätzt werden. Danke, Duncan – pieSquared

+0

Ich würde vorschlagen, einen Fehlerbericht einzureichen. –

Antwort

20

Dies ist ein schwieriger. Doing folgende Arbeiten ohne Probleme:

double moneyAmount = 1256.34; 
NSLocale *french = [[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"]; 
NSNumberFormatter *currencyStyle = [[NSNumberFormatter alloc] init]; 

[currencyStyle setLocale:french]; 
[currencyStyle setNumberStyle:NSNumberFormatterCurrencyStyle]; 
NSNumber *amount = [NSNumber numberWithDouble:moneyAmount]; 
NSString *amountString = [currencyStyle stringFromNumber:amount]; 

NSNumber *pAmount = [currencyStyle numberFromString:amountString]; // == 1256.34 

der Ausgang der -currencyGroupingSeparator Methode jedoch gibt die Zeichenfolge \u00a0, ein non-breaking space, anstatt die erwarteten ,.

Die Formatierungsklassen (unter anderem auch die Regex-Klassen) unter OS X/iOS verwenden die ICU library, die auch von anderen Projekten verwendet wird. Ich habe mindestens two andere bug Berichte in Bezug auf dieses spezielle Problem gefunden. Es scheint, dass dies expected Verhalten ist, obwohl. (Ich habe einige Zeit damit verbracht, die ICU-Quelle zu durchsuchen, um herauszufinden, wo dies definiert ist, aber es ist ein Labyrinth.)

Meine Empfehlung, vorläufig wäre -setLenient:YES an den Währungsformatierer zu übergeben. Vielleicht reichen Sie sogar einen Fehlerbericht mit Apples Radar ein.

+2

'setLenient:' ist Gold. –

2

Haben Sie versucht, die Region zu Frankreich in den Einstellungen festlegen und dann für die Zeichenfolge die numerische Menge zu bekommen versuchen? Oder Sie können das lokale des Zahlformatierers mit setLocale: manuell einstellen. NSNumberFormatter verwendet das jeweilige Gebietsschema, um herauszufinden, welche Zahlen eine Zeichenfolge sind. Wenn Sie nur benötigen, dass der Benutzer eine lokalisierte Währungszeichenfolge für seinen Bereich eingeben kann, ändern Sie das System in dieses Gebietsschema und testen Sie dann. Wenn Sie möchten, dass der Benutzer mehrere Formate einfügen kann, dann fügen Sie eine Art Auswahlsystem hinzu, damit Sie wissen, was sie eingeben.

+0

Ja, alles wird unter dem richtigen Gebietsschema ausgeführt. Ich muss nicht mehrere Währungen unterstützen, sondern nur mit Zeichenfolgen im nativen Gebietsschema des Benutzers arbeiten. Im obigen Beispiel ist das Gebietsschema auf Frankreich (oder Deutschland usw.) eingestellt. Ich werde die Frage aktualisieren;) – pieSquared

1

Ich habe eine hässliche Antwort unter Verwendung NSScanner

NSArray * testStrings = [NSArray arrayWithObjects:@"12,34 €", @"12,34" ,@"12.345,67 €" ,@"12.345,67", nil]; 

    NSCharacterSet * charset = [[NSCharacterSet decimalDigitCharacterSet] invertedSet]; 

    for(NSString * s in testStrings) 
    { 
     s = [s stringByReplacingOccurrencesOfString:@"." withString:@""]; 
     s = [s stringByReplacingOccurrencesOfString:@"," withString:@"."]; 
     NSScanner * scanner = [NSScanner scannerWithString:s]; 
     [scanner setCharactersToBeSkipped:charset]; 
     float f; 
     [scanner scanFloat:&f]; 
     NSLog(@"float output is %.2f",f); 
    } 

output:
2011-05-05 12: 56: 25.460 ScannerTest [10882: 903] float Ausgang 12.34
2011-05-05 12 : 56: 25.473 ScannerTest [10882: 903] Fließkommaausgabe ist 12.34
2011-05-05 12: 56: 25.474 ScannerTest [10882: 903] Fließkommaausgabe ist 12345.67
2011-05-05 12: 56: 25.475 ScannerTest [ 10882: 903] Float-Ausgabe ist 12345.67

+0

toll, arbeite für mich.save meine zeit :) – Dhaval

2

Ich verifiziert, dass (zumindest auf iOS 4.3) mit dem Flag [formatter setLenient: YES] funktionierte für mich mit Euros. Ohne dieses Flag gibt der Formatierer keine korrekten Werte für Euro zurück.

0

Mit den Standardeinstellungen (lenient = NO) werden nur Zeichenfolgen in Zahlen konvertiert, wenn sie genauso formatiert sind wie die Zeichenfolgen, die beim Formatieren von Zahlen in Zeichenfolgen erstellt werden.

Wenn Sie also nicht-milde Conversions verwenden möchten, sollten Sie beachten, dass in vielen Gebietsschemas (alle?) Bedeutet, dass Leerzeichen in der Eingabezeichenfolge nicht brechen dürfen (\u00a0). Nämlich:

NSString *amount = @"10 000,00 €"; 

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
formatter.numberStyle = NSNumberFormatterCurrencyStyle; 

formatter.locale = [[NSLocale alloc] initWithLocaleIdentifier: @"fr_FR"]; 

NSNumber *number = [currencyFormatter numberFromString: amount]; 

Dies wird das erwartete Ergebnis nicht produzieren, da das number Variable gleich Null sein wird. Um das gewünschte Ergebnis zu erhalten, verwenden non-breaking Leerzeichen an beiden Stellen der Zeichenfolge (als Tausendertrennzeichen und ein Währungssymbol Separator):

amount = @"10\u00a0000,00\u00a0€"; 

Dann wird die Umwandlung als erwartet passieren.

Natürlich, wenn Sie nachsichtig Conversions verwenden möchten, dann ist dies der einfachste Weg zu gehen, und es wird wahrscheinlich die beste Option sein, um menschliche Eingabe zu behandeln.

Auf der anderen Seite kann eine milde Interpretation der Zeichenfolgen bei der Verarbeitung von maschinengenerierten Daten nicht wünschenswert sein, da Sie die Möglichkeit verlieren, die Richtigkeit der Eingabedaten zu überprüfen.

0

Der Weg, um dies in Swift zu tun ist:

var locale = NSLocale.currentLocale() 
    var formatter = NSNumberFormatter() 
    formatter.locale = NSLocale(localeIdentifier: "en_US") 
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle 

    var moneyDouble = formatter.numberFromString(textField.text)?.doubleValue 

die TextField.text Angenommen die Zahl eingegeben wird.

2

Sein Arbeitscode in Swift ..

let formatter = NumberFormatter() 
    formatter.usesGroupingSeparator = true 
    formatter.locale = Locale(identifier: "de_DE") 
    formatter.numberStyle = NumberFormatter.Style.currency 
    formatter.string(from: NSNumber(floatLiteral: InputAsDoubleValue))! 

Identifiers:

  • für Deutsch-"de_DE"
  • für US-"en_US"
  • für Frankreich - "fr_FR"

Der formatierte Wert wird auch mit dem entsprechenden Währungssymbol zurückgegeben.

Verwandte Themen