| 

.NET C# Java Javascript Exception

4
Hallo zusammen,

ich stehe vor folgendem Problem: In meiner iPhone-App muss ich an einer Stelle die im Gerät eingestellte Systemsprache auswerten. Dazu habe ich mir bis jetzt folgenden Code gebastelt:

NSString *locale = [[NSLocale currentLocale] localeIdentifier];
NSLog(@"%@", locale);
if (locale == @"de_DE") {
//Tu etwas...
} else {
//Tu etwas anderes...
}


Leider führt das aber nicht zum gewünschten Ergebnis. Lasse ich mir den Inhalt der Variablen "locale" via NSLog ausgeben, erhalte ich zwar bei meinen aktuellen Tests wie in der Abfrage geschrieben "de_DE" zurück, allerdings wird fälschlicherweise der Inhalt der else-Schleife ausgeführt. Und an dieser Stelle komme ich im Moment einfach nicht weiter!

Ich bin für jeden Tipp und jeden Hinweis sehr dankbar! Letztliches Ziel soll sein, dass ich die aktuelle Systemsprache abfrage und dann - je nachdem, ob diese Deutsch ist oder nicht - verschiedene Dinge tue.

Falls ihr von mir noch nähere Infos braucht lasst es mich wissen!

Beste Grüße,
Thomas
News:
21.08.2011
Sillivan 479 1 7
5 Antworten
6
Hallo Thomas,

Das Problem ist, dass Du hier pointer - also auf Objektidentität - vergleichst und *keine* Objektinhalte. Deshalb hatte AlexanderF, oben schon den richtigen Riecher ;-)

Die Pointer werden in Deinem Fall nie identisch sein, da Du die Variable locale auf ein anderes Objekt zeigen wird, als der konstante String @"de".

Daher läufst Du auch stets in den else Zweig ;)

Nun hast Du oben ja versucht zu widerlegen, dass dem so ist und in der Tat das Snippet oben von Dir wird auch funktionieren. Und das kurioserweise mit Recht!

WTF? Nun, das ist keine Magie, sondern ein Feature! Alldiweil hier eine implizite Optimierung des Compilers greift - selbst dann, wenn Du mit O0 übersetzt.

Nun, Du schreibst oben

NSString *locale = @"de";
if (locale == @"de") {
//Abfrage funktioniert, springt in diese Schleife!
} else {
//Hier passiert nichts...
}


Was passiert da? Du weist locale den konstanten String zu und vergleichst nun den unten gegen einen anderen ebenfalls konstanten String. Du merkst "Konstantheit" ist hier das Schlüsselwort.

Also, dass die Strings Konstant sind erkennt der Compiler und sagt sich - oh - dann kann ich das ja gleich beim Kompilieren prüfen und da die Strings inhaltsidentisch sind, wird er den Ausdruck true übersetzen. Also den else Zweig gar nicht erzeugen!

BTW - deswegen sollte man Konstantheit - noch besser das Schlüsselwort const auch nutzen wo möglich, da dies ein prima Möglichkeit ist, den Compiler explizit auf Optimierungsmöglichkeiten hinzuweisen. Der GCC oder LLVM/Clang, der beim Xcode dabei ist, ist aber schon ziemlich smart, sodass er das auch schon selbst in gewissen Rahmen erkennt.

Ich hoffe, ich konnte das verständlich rüberbringen ;)

So, zurück zu Deinem Fall.

Du musst also tatsächlich die Inhalte der Objekte vergleichen und nicht die Objektreferenzen! Also -[NSString isEqualToString:] verwenden!

if ([locale isEqualToString:@"de"]) {
//Tu etwas mit der Deutschen locale...
} else {
//Tu etwas anderes...
}


...oder wenn erforderlich statt isEqualToString eben eine andere Vergleichsfunktion von NSString benutzen... ;)

Dann wird es auch funktionieren ;)

Ach noch was zur Info: Da NSString - wie alle Cocoa Klassen - von NSObject abgeleitet ist, kannst Du wahlweise auch isEqual: verwenden und das würde genauso funktionieren. NSString implementiert diese Methode auch - er überlädt sie - und macht semantisch das Selbe wie isEqualToString:

Allerdings wird isEqual: von NSString - da es von NSObjekt stammt und somit jede von NSObject abgeleitet Klasse besitzt - implizit erst mal schauen, ob die Objekttypen identisch sind und erst wenn dem so ist den Stringinhalt vergleichen. Schließlich macht es nur Sinn Objekte des gleichen Typs zu vergleichen.

Ich würde daher aus Performancegründen isEqualToString: verwenden, weil der explizit nur für Strings gilt und damit die Objekttypenidentität schon erfüllt ist.

Happy codin'! - Peter -
22.08.2011
hdusel 195 4
3
Leider kenn ich mit Objective C noch nicht so gut aus, aber vielleicht könnte es ähnlich wie bei Java sein?

Aufgrund der Speicherverwaltung kann man die Operatoren ==, != nur auf primitive Datentypen anwenden (int,boolean etc.). Komplexe Datentypen wie Strings und andere Objekte müssen per equals-Funktion verglichen werden - Beispiel:
var1.equals(var2)


Aber wie das in ObjC genau aussehen würde, kann ich leider nicht sagen - sorry
21.08.2011
AlexanderF 185 1 6
1
Hallo,

guck mal hier: Choosing localizations
21.08.2011
michlG 1,7k 1 5
1
Vielen Dank für eure beiden Antworten! Ich bin beidem einmal nachgegangen, aber leider ohne Erfolg.

Zu Antwort 1: Ich habe die Abfrage entsprechend getestet, indem ich eine NSString-Variable erstellt und ihr einen festen Wert zugewiesen habe. Diesen habe ich dann in die Abfrage gesetzt und das hat funktioniert; Strings dürften sich also auch unter Objective-C auf diese Art und Weise abfragen lassen. Hier mein entsprechender Test-Code:

NSString *locale = @"de";
if (locale == @"de") {
//Abfrage funktioniert, springt in diese Schleife!
} else {
//Hier passiert nichts...
}


Zu Antwort 2: Ich habe meinen Code einmal wie in dem von dir geposteten Link entsprechend wie folgt abgeändert:

NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
NSArray *languages = [defs objectForKey:@"AppleLanguages"];
NSString *locale = [languages objectAtIndex:0];


Auf diese Art und Weise hat die Variable "locale" zum Beispiel den Wert "de" oder "en", je nach eingestellter Systemsprache; das funktioniert also schon richtig, jedoch wird nichtsdestotrotz die Abfrage falsch ausgewertet:

if (locale == @"de") {
//Hier müsste er auf meinem Testsystem hineinspringen, tut er aber nicht!
} else {
//Stattdessen springt er in die else-Schleife, obwohl "locale" den Wert "de" besitzt
}


Wenn ich mein System auf Englisch umstelle und somit der Wert der Variablen "locale" "en" entspricht und ich dahingehend die Abfrage anpasse, tritt der selbe Fehler auf. Leider weiß ich da aktuell gar nicht weiter und verstehe auch nicht wo das Problem liegt, da die Variable - wenn ich sie auslese - genau den Wert besitzt, den ich abfrage.

Für weitere Ideen und Vorschläge zu diesem Problem bin ich daher offen, es macht mich aktuell wahnsinnig! :-) Nichtsdestotrotz schon einmal vielen Dank für eure Antworten!

Beste Grüße,
Thomas
21.08.2011
Sillivan 479 1 7
0
Hallo Peter,

besten Dank für deine Antwort! An dieser Stelle muss ich auch noch einmal ausdrücklich AlexanderF danken; wie du geschrieben hast war sein Ansatz genau richtig, ich habe es lediglich falsch umgesetzt. Mit dem von dir genannten Beispielcode klappt es wunderbar und genau so wie es soll; vielen vielen Dank dafür! :-) Auch deine ausführliche Erklärung hat mir sehr weitergeholfen; nun weiß ich auch in dieser Hinsicht wieder etwas besser Bescheid! ;-)

Beste Grüße,
Thomas
22.08.2011
Sillivan 479 1 7

Stelle deine Ios-Frage jetzt!