NSNumberformatter in einer Tools Klasse

  • ok, zumal ich unter Android sogar nicht in nativem Java programmiere, sondern mit Basic4Android,
    da ist das nochmal was anderes. Da habe ich einfach Subroutinen die ich nach belieben aufrufen kann.

    Daher wollte ich eine Klasse mit Klassenmethoden, wo ich bestimmte Routinen drin habe, die ich immer wieder
    an verschiedenen Stellen im Programm benötige.

    Ich werde mir jetzt nochmal die Grundlagen über Klassen, Methoden und Probertys reinziehen.
    MfG. Bernhard
    (www.hb-mobilesoft.com)
  • macmoonshine schrieb:

    Paulsche schrieb:

    ok, zumal ich unter Android sogar nicht in nativem Java programmiere, sondern mit Basic4Android,

    Oh, auch noch ein Programmiersprachenparadigmenwechsel; dann wird's richtig lustig. ;)


    Ja, war für mich das bequemste als ich für Android programmieren angefangen haben, da ich vor 30 Jahren
    mal mit Basic programmiert habe ;) . Das rächt sich jetzt eben, aber nun will ich ja das "richtige programmieren"
    lernen, programmieren und programmieren ist halt nicht das Selbe und ich bin ja noch Lernfähig :)
    MfG. Bernhard
    (www.hb-mobilesoft.com)
  • Wat wisste machen ohne Categories?
    Im Prinzip sind diese Statischen Methoden in Utils-Klassen nichts Anderes als Funktionssammlungen. Java braucht nun mal für (fast) alles ein Objekt, weshalb man in Java nicht einfach so ein paar Funktionssammlungen reinwerfen kann. Da muss man den Umweg über eben diese Utils-Klassen mit statischen Methoden gehen.

    Naja, Java hat aber bestimmt auch irgendwelche Vorteile. ;)
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Paulsche schrieb:

    Ich werde mir jetzt nochmal die Grundlagen über Klassen, Methoden und Probertys reinziehen.

    Und im Anschluss solltest Du Dir auf Apples Seiten ein paar Beispielcodes zu Anwendungen ansehen, die Dich interessieren könnten.
    Eventuell bekommst Du dann ein Gefühl dafür, wie das alles zusammenspielt.
    «Applejack» "Don't you use your fancy mathematics to muddle the issue!"

    Iä-86! Iä-64! Awavauatsh fthagn!

    kmr schrieb:

    Ach, Du bist auch so ein leichtgläubiger Zeitgenosse, der alles glaubt, was irgendwelche Typen vor sich hin brabbeln. :-P
  • Paulsche schrieb:

    mattik schrieb:

    Ich verstehe immer noch nicht, warum du unbedingt die Funktionalität eines NSNumberFormatters in eine Klassenmethode kapseln willst - meiner Meinung nach hast du davon nur den Nachteil, dass du dich fortan händisch mit dem ganzen Zeug herumschlagen musst. Außerdem erzeugst du für jede Formatierung eine NSNumberFormatter-Instanz, lässt sie eine Zahl formatieren und wirfst sie dann weg. Das ist fürchterlich ineffizient.

    Die Formatter haben einen eigenen Zustand, das ist keine Einschränkung, sondern ein Feature (ein tolles!). Sie dürfen (und sollen) wiederverwendet werden. Dazu muss man sie nur an die entsprechenden Textfelder hängen und fertig, der Rest passiert automatisch.


    Ok, ich möchte nach jeder Textfeldeingabe den string (Zahl) in ein individuelles Dezimalzahlformat (1,2,3 Kommastellen) formatieren können.
    Das mit der jedesmal instanzierung leuchtet ein daß das nicht sinnvoll ist, ich sollte wohl in jeder Controllerklasse in ViewDidLoad die Initialisierung machen
    und nach Textfeldeingabe die restliche Anpassung für die Dezimalstellen, richtig ?

    Hatte dann wohl einen Denkfehler ?

    Ich verstehe die Sache mit der individuellen Formatierung nicht ganz. Jedes Feld kann eine Zahl ja nur in einer Art darstellen (zumindest zu einem bestimmten Zeitpunkt). Und jedes Feld sollte auch eine Art der Eingabe haben (wenn man keine Usability-Katastrophe haben will). Wenn du verschiedene Felder hast, die unterschiedliche Formatierungen benötigen ist das kein Problem: Man kann ja mehrere Formatter haben.

    Beispiel: Ich denke mir, dass du z.B. Felder für gefahrene km (meinetwegen eine Nachkommastelle), getankte Liter (zwei Nachkommastellen), bezahltes Geld (auch zwei Nachkommastellen, Währung) und Spritpreis (drei Nachkommastellen hast). Das lässt sich ohne eine einzige Zeile Code umsetzen: Im Interface Builder vier NumberFormatter erzeugen: KMFormatter, LiterFormatter, GeldFormatter, PreisProLiterFormatter. Auf die gewünschte Darstellung einstellen. Und dann an die entsprechenden Textfelder hängen (ctrl-Klick auf das Textfeld, die Linie auf den Formatter ziehen und dann "formatter" wählen). Fertig - alles automatisch, kein Code geschrieben. Und das sollte die meisten (wirklich sehr viele) Fälle abdecken.

    Wenn sich zur Laufzeit das Verhalten eines Feldes ändern soll, kann man a) den entsprechenden Formatter ändern, b) einen anderen Formatter zuweisen oder c) die Views tauschen - je nach dem, was sinnvoll ist.

    Wenn du allerdings tatsächlich ein und den selben Wert aus ein und dem selben Feld in mehreren Auflösungen brauchst (wobei ich mir nicht vorstellen kann, dass das irgend ein Benutzer verstehen würde) wäre das eine Sache im Code. Das sind dann aber separate Rundungsschritte, die nichts mit der Formatierung der Zahl selbst zu tun haben - wie gesagt, ein bestimmtes Feld muss eine bestimmte Zahl ja auf eine bestimmte Art formatieren.

    Falls du etwas ganz anderes vor hast, schildere doch mal ganz genau an einem Beispiel, was du machen willst und weshalb das mit den Formattern auf die normale Art deiner Meinung nach in dem Fall nicht funktioniert. Ich kann mir keinen einzigen (sinnvollen) vorstellen, in dem man solche Umwege braucht (was natürlich auch an meiner mangelnden Phantasie liegen kann).
    Multigrad - 360°-Produktfotografie für den Mac
  • /quote]
    Beispiel: Ich denke mir, dass du z.B. Felder für gefahrene km (meinetwegen eine Nachkommastelle), getankte Liter (zwei Nachkommastellen), bezahltes Geld (auch zwei Nachkommastellen, Währung) und Spritpreis (drei Nachkommastellen hast). Das lässt sich ohne eine einzige Zeile Code umsetzen: Im Interface Builder vier NumberFormatter erzeugen: KMFormatter, LiterFormatter, GeldFormatter, PreisProLiterFormatter. Auf die gewünschte Darstellung einstellen. Und dann an die entsprechenden Textfelder hängen (ctrl-Klick auf das Textfeld, die Linie auf den Formatter ziehen und dann "formatter" wählen). Fertig - alles automatisch, kein Code geschrieben. Und das sollte die meisten (wirklich sehr viele) Fälle abdecken.
    [/quote]

    Genau das meinte ich eigentlich, ich habe Textfelder die unterschiedliche Dezimalstellen zeigen sollen. Hierzu unterschiedliche Formatter definieren wäre eine Möglichkeit,
    das muss ich mal prüfen. Im IB das zuweisen habe ich absichtlich ausser Acht gelassen, da ich dies im Code lernen wollte, denn es wird ja später bestimmt
    Labels geben die ich nur im Code erzeugen kann/werde.
    Ich muss das mal im IB versuchen, finde nur den NSNumberformatter in der Objektlybrary nicht.
    MfG. Bernhard
    (www.hb-mobilesoft.com)
  • macmoonshine schrieb:

    Das mit den Numberformattern in Textfeldern geht leider nur unter OSX. Der OP redet jedoch anscheinend über ein iOS-Projekt. (Falsches Forum, tststs) ;) :D


    Oh, da war ich verwirrt. Ja, in iOS gibt es zwar auch NSNumberFormatter aber da benutzt man sie wenn man will im delegate vom UITextField.
    (Ich dachte auch es ginge um OSX)

    Google nach "UITextField Realtime Formatting" sollte helfen
  • Paulsche schrieb:

    Also, ich habe das jetzt so gelöst,eine Klasse Tools erstellt, darin KlassenMethoden für meine Tools-Funktionen die ich immer wieder im Code benötige.
    Beispiel: KlassenMethode um Eingabe in Textfelder für Dezimalzahlen formatieren.

    Quellcode

    1. + (NSString*)stringWithDecimalNumber :(NSString*)stringWithNumber :(NSUInteger)minimumFractionDigits :(NSUInteger)maximumFractionDigits
    2. {
    3. NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    4. [formatter setLocale:[NSLocale currentLocale]];
    5. formatter.numberStyle = NSNumberFormatterDecimalStyle;
    6. formatter.minimumFractionDigits = minimumFractionDigits;
    7. formatter.maximumFractionDigits = maximumFractionDigits;
    8. double numberFromString = [[formatter numberFromString:stringWithNumber] doubleValue];
    9. NSString *stringFromNumber = [formatter stringFromNumber:[NSNumber numberWithDouble:numberFromString]];
    10. return stringFromNumber;
    11. }
    Alles anzeigen

    Aufruf der Methode:

    Quellcode

    1. _tf02liter.text = [Tools stringWithDecimalNumber :_tf02liter.text :3 :3]; // Textfeld mit formatiertem Dezimalstring


    Ich denke die Lösung ist so ok, mit Kategorie wäre es auch gegangen, aber da müsste ich für jede Tool-Funktion eine Kategorie mit jeweils eigenen .h .m Dateien erstellen.
    Oder liege ich mit meiner Lösung voll daneben ? Bin mir noch unsicher.
    Mal generell und um meine narzisstische Persönlichkeitsstörung hervorzukehren:

    Wenn ich dir einen Rat gebe, ist der in allermeisten Fällen zutreffend. Es lohnt sich also regelmäßig, ihm zu folgen.
    Es hat noch nie etwas gefunzt. To tear down the Wall would be a Werror!
    25.06.2016: [Swift] gehört zu meinen *Favorite Tags* auf SO. In welcher Bedeutung von "favorite"?
  • ok, ich habe jetzt mal folgendes gemacht und rechne gleich mit Steinigung :whistling: :

    Tools.h

    Quellcode

    1. + (NSNumber*)numberFromDecimalString :(NSString*)stringWithDecimalNumber;
    2. + (NSString*)stringFromNumber :(NSNumber*)decimalNumber fractionDigits:(NSUInteger)fractionDigits;
    3. + (NSString*)stringWithDecimalNumber :(NSString*)StringWithNumber fractionDigits:(NSUInteger)fractionDigits;


    Tools.m

    Quellcode

    1. +(NSNumber*)numberFromDecimalString :(NSString*)stringWithDecimalNumber
    2. {
    3. NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    4. [formatter setLocale:[NSLocale currentLocale]];
    5. formatter.numberStyle = NSNumberFormatterDecimalStyle;
    6. NSNumber *numberFromString = [formatter numberFromString:stringWithDecimalNumber]; // String in Dezimalzahl für Rechenoperationen
    7. return numberFromString;
    8. }
    9. +(NSString*)stringFromNumber :(NSNumber*)decimalNumber fractionDigits:(NSUInteger)fractionDigits
    10. {
    11. NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    12. [formatter setLocale:[NSLocale currentLocale]];
    13. formatter.numberStyle = NSNumberFormatterDecimalStyle;
    14. formatter.minimumFractionDigits = fractionDigits;
    15. formatter.maximumFractionDigits = fractionDigits;
    16. NSString *stringFromNumber = [formatter stringFromNumber:decimalNumber]; // String von Dezimalzahl aus Rechenoperationen (engl.Format) in deutsches format
    17. return stringFromNumber;
    18. }
    19. + (NSString*)stringWithDecimalNumber :(NSString*)stringWithNumber fractionDigits:(NSUInteger)fractionDigits // String als Dezimalzahl formatieren
    20. {
    21. NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    22. [formatter setLocale:[NSLocale currentLocale]];
    23. formatter.numberStyle = NSNumberFormatterDecimalStyle;
    24. formatter.minimumFractionDigits = fractionDigits;
    25. formatter.maximumFractionDigits = fractionDigits;
    26. double numberFromString = [[formatter numberFromString:stringWithNumber] doubleValue];
    27. NSString *stringFromNumber = [formatter stringFromNumber:[NSNumber numberWithDouble:numberFromString]];
    28. return stringFromNumber;
    29. }
    Alles anzeigen


    Aufruf

    Quellcode

    1. _tf02literpreis.text = [Tools stringWithDecimalNumber:_tf02literpreis.text fractionDigits:3]; // Nach Eingabe in Textfeld, formatiert als Dezimalstring zur Anzeige
    2. double literpreis = [[Tools numberFromDecimalString:_tf02literpreis.text] doubleValue]; // Numbers von Strings der Textfelder zum rechnen
    3. literpreis = rechnung / liter; // Berechnung des Literpreises
    4. NSNumber *num_asNSNumber = (NSNumber*) [NSNumber numberWithDouble:literpreis]; // Berechneter Literpreis in NSNumber umwandeln
    5. _tf02literpreis.text = [Tools stringFromNumber:num_asNSNumber fractionDigits:3]; // Ergebnis als Dezimalzahl in Textfeld übernehmen


    Es funktioniert wunderbar, liege ich damit sehr daneben ?
    Sollte ich doch lieber Kategorien nehmen wenn es so funktioniert ?
    Ich habe jetzt einfach mal probiert, ist ja auch nötig zum lernen, wen ich damit aber
    wirklich daneben liege, was wäre die sauberere Art, dann schreibe ich es um.
    MfG. Bernhard
    (www.hb-mobilesoft.com)
  • Das einzige was mich stört ist das immer neue NSNumberFormatter Instanzen erzeugt werden.
    Die NSNumberFormatter sind ja extra so gebaut, dass sie von vielen Objekten benutzt werden können.

    Ich würde also für die häufigsten Formate drei NSNumberFormatter erzeugen und dann in der Tools Klasse benutzen.
    So wird für jede Umwandlung immer ein neuer erzeugt und weggeworfen.

    Aber wenn wir mal ehrlich sind, dass ist jetzt nichts was 1000 Mal pro Sekunde geschieht.
    Behalte nur im Hinterkopf dass man eigentlich keine "Wegwerf-Objekte" erzeugen sollte...