2012-03-28 6 views
1

Ich entwickle eine Anwendung, in der ich verschiedene Währungsformate behandeln möchte, abhängig vom aktuellen Gebietsschema. Mit einer NSNumberFormatter kann ich eine Zahl ohne Probleme in String und zurück übersetzen.Wie lege ich einen Währungszeichenfolgenwert auf ein UITextField fest, wobei die Codierung beibehalten wird?

Aber, wenn ich den String-Wert in eine UITextField und später bekomme es zurück, werde ich nicht in der Lage, die Zeichenfolge zurück in eine Zahl und ich werde stattdessen einen Wert erhalten.

Hier ist ein Beispielcode das Problem zu erklären:

NSNumberFormatter *nf = [Utils currencyFormatter]; 
NSNumber *n = [NSNumber numberWithInt:10000]; 
NSString *s = [nf stringFromNumber:n]; 
NSLog(@"String value = %@", s); 
UITextField *t = [[UITextField alloc] init]; 
// I put the string into the text field ... 
t.text = s; 

// ... and later I get the value back 
s = t.text; 
NSLog(@"Text field text = %@", s); 
n = [nf numberFromString:s]; 
NSLog(@"Number value = %d", [n intValue]); 

wo die currencyFormatter Methode definiert ist auf diese Weise:

+ (NSNumberFormatter *)currencyFormatter 
{ 
    static NSNumberFormatter *currencyFormatter; 
    if (!currencyFormatter) { 
     currencyFormatter = [[NSNumberFormatter alloc] init]; 
     [currencyFormatter setFormatterBehavior:NSNumberFormatterBehavior10_4]; 
     [currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle]; 
     [currencyFormatter setLocale:[NSLocale currentLocale]]; 
     if ([currencyFormatter generatesDecimalNumbers] || [[currencyFormatter roundingIncrement] floatValue] < 1) { 
      [currencyFormatter setGeneratesDecimalNumbers:YES]; 
      [currencyFormatter setRoundingIncrement:[NSNumber numberWithFloat:0.01]]; 
     } 
    } 

    return currencyFormatter; 
} 

(Die innere if verwendet zu zwingen, den Formatierer immer rund bis zur kleinsten Dezimalstelle, zB auch für CHF-Werte).

Was ich in der Konsole erhalten, ist dies:

2012-03-29 00:35:38.490 myMutuo2[45396:fb03] String value = € 10.000,00 
2012-03-29 00:35:38.494 myMutuo2[45396:fb03] Text field text = € 10.000,00 
2012-03-29 00:35:38.497 myMutuo2[45396:fb03] Number value = 0 

Das seltsame ist, dass der Abstand Charakter zwischen und 1 in der ersten Zeile in der Konsole über einen mitten in der Luft Punkt dargestellt, während in In der zweiten Zeile verschwindet dieser Punkt. Ich glaube, dass dies ein Problem mit der Codierung ist.

Kann mir jemand helfen, dieses Problem zu lösen? Vielen Dank!

bearbeiten

änderte ich meinen Testcode dazu:

NSNumberFormatter *nf = [Utils currencyFormatter]; 
NSNumber *n = [NSNumber numberWithInt:10000]; 
NSString *s = [nf stringFromNumber:n]; 
NSLog(@"String value = %@ (space code is %d)", s, [s characterAtIndex:1]); 
UITextField *t = [[UITextField alloc] init]; 
t.text = s; 
s = t.text; 
NSLog(@"Text field text = %@ (space code is %d)", s, [s characterAtIndex:1]); 
n = [nf numberFromString:s]; 
NSLog(@"Number value = %d", [n intValue]); 

dies zu entdecken:

2012-03-29 02:29:43.402 myMutuo2[45993:fb03] String value = € 10.000,00 (space code is 160) 
2012-03-29 02:29:43.405 myMutuo2[45993:fb03] Text field text = € 10.000,00 (space code is 32) 
2012-03-29 02:29:43.409 myMutuo2[45993:fb03] Number value = 0 

Die NSNumberFormatter schreibt den Raum als non-breaking Raum (ASCII-Zeichen 160) und dann UITextField diesen Raum als ein einfaches Leerzeichen (ASCII-Zeichen 32) neu codiert. Eine bekannte Problemumgehung für dieses Verhalten? Vielleicht könnte ich einfach den Platz durch einen freien Platz ersetzen, aber ... wird es für alle Locales funktionieren?

+0

es funktioniert nicht nur für Ihre Währung Gebietsschema. Ich habe es überprüft und den gleichen Nullwert bekommen, wie du gesagt hast. –

+0

Siehe meine bearbeitete Antwort zum zweiten Mal. Dies kann dir etwas helfen. –

Antwort

0

Ich konnte dieses Problem lösen, nur die UITextField durch ein erweiternd benutzerdefinierte Klasse. In dieser neuen Klasse habe ich einen neuen @property vom Typ NSString, in dem ich den "berechneten" String-Wert für das Textfeld speichern. Diese Zeichenfolge wird niemals geändert und behält die ursprüngliche Codierung des Inhalts des Textfelds bei.

Wenn Sie erneut mit dem ursprünglichen unberührten Inhalt des Textfelds arbeiten müssen, müssen Sie sich auf diese neue Eigenschaft beziehen, anstatt sich auf die Eigenschaft text zu beziehen.

Die Verwendung eines separaten String-Containers ist die einzige Möglichkeit, diese merkwürdigen Codierungsänderungen zu vermeiden.

0

Eine mögliche Problemumgehung: Sie könnten versuchen, nur die Zahlenwerte (und die Punktierung) über ein Regex-Muster zu analysieren und einen Währungswert basierend auf dieser Zahl zu erstellen. Wenn Sie es auf diese Weise tun, ist es vielleicht noch besser verzeihbar für den Benutzer, wenn er ein anderes Währungssymbol oder andere Symbole eintippte, die nicht dort sein sollten ...

+0

Ich mache dies bereits in einer früheren Version des Codes. Aber ich bekomme seltsame Fehler, Ausnahmen und Abstürze, wahrscheinlich mit einem seltsamen Locale. Ich würde wirklich gerne die Magie des 'NSNumberFormatter' verwenden, um all diese benutzerdefinierte Handhabung der Strings loszuwerden und in einer" kontrollierten "Umgebung zu arbeiten, in der ich die Strings/Zahlen mit dem gleichen Formatter-Objekt kodiere und dekodiere. – marzapower

+0

Übrigens ... was der Benutzer in 'UITextField' steckt, wird tatsächlich durch einen Aufruf der' stringFromNumber: 'Methode von' NSNumberFormatter' erzeugt, so dass ich immer weiß, dass das, was das Textfeld enthält, korrekt formatiert wurde. Es ist nicht notwendig, mehr Logik hinzuzufügen, um diesen Wert zu interpretieren. – marzapower

+0

Dann könnten Sie einfach den vom Benutzer eingegebenen Wert für die spätere Verwendung speichern? Warum brauchen Sie den Inhalt des Textfelds neu zu konvertieren? – calimarkus

Verwandte Themen