2013-03-20 1 views
9

Secondo la documentazione, [NSDecimalNumber decimalNumberWithString:] dovrebbe utilizzare il separatore locale decimali:NSDecimalNumber decimalNumberWithString: ignora parametri locali

Se il NSDecimalSeparator è un periodo (come viene utilizzato, ad esempio, negli Stati Uniti) o un virgola (come viene utilizzata, ad esempio, in Francia) dipende dalle impostazioni internazionali predefinite.

Ma quando l'ho provato, questo codice:

NSLog(@"%@", [NSDecimalNumber decimalNumberWithString:@"100,1"]); 
NSLog(@"%@", [NSDecimalNumber decimalNumberWithString:@"100,1" locale:NSLocale.currentLocale]); 

Dà ...

100 
100.1 

... come uscita su entrambi iOS 5 e iOS 6. Ho provato con svedese e francese come impostazioni regionali poiché entrambi questi paesi usano la virgola (,) come separatore decimale.

L'uscita non dovrebbe essere uguale?

(so che posso usare [NSDecimalNumber decimalNumberWithString: locale:] per forzare il comportamento, in modo da questa domanda non è di trovare un'alternativa, solo se si tratta di un bug o sto facendo qualcosa di sbagliato)

risposta

6

NSDecimalNumber è semplicemente una classe di archiviazione per dati di tipo numerico. È in esecuzione un parser (NSNumberFormatter) sulla stringa che si passa per creare il suo numero. Il motivo per cui la seconda istruzione del registro funziona "meglio" è perché il primo utilizza il formato di numero predefinito (è come è en_US, ma non posso verificarlo, vedere il colpo di modifica per ulteriori informazioni.) da analizzare e "100,1" non è un numero valido, quindi la parte "non numerata" viene rimossa. Specificando un'impostazione internazionale che utilizza "," separatori decimali, acquisisce correttamente il numero completo.

Quando si NSLog() un NSDecimalNumber si chiama semplicemente -description, che non ha un contesto locale e può stampare, più o meno, qualunque cosa desideri.

Se si desidera stampare i numeri correttamente formattati usare NSNumberFormatter in questo modo:

NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:@"100.1"]; 

NSLog(@"%@", number); 

NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 

[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; 

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

[formatter setLocale:locale]; 

NSLog(@"%@", [formatter stringFromNumber:number]); 

Oppure, brevemente

NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:@"100.1"]; 
NSLog(@"%@", [NSNumberFormatter localizedStringFromNumber:number numberStyle:NSNumberFormatterDecimalStyle]); 

se si desidera utilizzare il locale corrente.

In sintesi:

  1. NSDecimalNumber è solo stoccaggio. La registrazione non riflette nulla sulla locale.
  2. Per ottenere NSDecimalNumber per memorizzare correttamente un numero, è necessario che le impostazioni internazionali corrispondano alle impostazioni internazionali dell'ingresso previsto (-[NSLocale currentLocale] è una buona scelta qui).
  3. Per visualizzare i numeri formattati correttamente per una determinata lingua, utilizzare NSNumberFormatter.

Edit:

Ok, ho fatto un po 'di ricerche su questo.

In GNUStep sembra che finisca per utilizzare il valore per NSDecimalSeparator in NSUserDefaults (da una rapida ricerca del codice).

Facendo qualche sperimentazione Ho scoperto che nessuno dei seguenti elementi influenzano il comportamento predefinito di analisi, per quanto posso dire:

  1. NSDecimalSeparator in NSUserDefaults.
  2. AppleLocale in NSUserDefaults.
  3. NSLocaleCode in NSUserDefaults.
  4. Il valore impostato per CFBundleDevelopmentRegion.
  5. I valori dell'ambiente LANG/LC_ALL/etc ....
  6. +[NSLocale systemLocale].

E ovviamente non è +[NSLocale currentLocale], poiché questa domanda deriva dal fatto che le impostazioni internazionali correnti non hanno alcun effetto.

+1

La domanda non riguarda la stampa, riguarda l'analisi. _ "il primo utilizza il formato del numero di default (en_US) per analizzare" _ - La mia domanda è perché en_US è il default quando la mia locale corrente è fr_FR. Quindi quando la documentazione dice che le impostazioni locali predefinite dipendono, quando differisce da en_US se non quando la mia locale corrente è fr_FR? – thejaz

+0

La documentazione non chiarisce che cosa fa diventare una locale la locale 'predefinita', anche se sembra che possa cambiare. Il mio pensiero iniziale era che potrebbe essere correlato al valore impostato per CFBundleDevelopmentRegion che ["Solitamente corrisponde alla lingua nativa dell'autore"] (https://developer.apple.com/library/ios/#documentation/General/Reference /InfoPlistKeyReference/Articles/CoreFoundationKeys.html) ma la modifica di quel valore non sembrava influenzare alcun comportamento. Se l'API o la documentazione non sono chiari, la cosa migliore da fare è [archiviare un radar] (https://bugreport.apple.com). – frozendevil

+0

Ho archiviato un radar di documentazione che consiglio di duplicare (rdar: // 13520160, http://openradar.appspot.com/radar?id=2878409); Ho anche aggiunto un po 'più di informazioni alla mia risposta. – frozendevil