mutablearry probleme

  • mutablearry probleme

    hallo leute,

    ich hab ein komisches problem. die folgende methode funktioniert nur einmal wärend einer laufzeit:

    Quellcode

    1. - (IBAction)card_change:(id)sender
    2. {
    3. NSMutableArray *card_ids = [NSMutableArray arrayWithArray:[preferences objectForKey:@"card_ids"]];
    4. int i = [card_listPopup indexOfSelectedItem];
    5. [[card_ids objectAtIndex:i] replaceObjectAtIndex:0 withObject:[card_id stringValue]];
    6. [[card_ids objectAtIndex:i] replaceObjectAtIndex:1 withObject:[card_name stringValue]];
    7. [[card_ids objectAtIndex:i] replaceObjectAtIndex:2 withObject:[card_address string]];
    8. [preferences setObject:card_ids forKey: @"card_ids"];
    9. [[NSUserDefaults standardUserDefaults] synchronize];
    10. [self reloadCardPopup];
    11. }
    Alles anzeigen


    wenn ich diese methode ein weiteres mal aufrufen will, dann bekomme ich eine fehlermeldung,
    dass card_ids nicht mutable ist und so replaceObjectAtIndex nicht funktioniert.
    wie gesagt, beim ersten mal funktioniert es.
    was koennte der grund dafür sein?

    sascha
  • RE: mutablearry probleme

    Hallo Sascha,

    warum es einmal functioniert weiss ich auch nicht so genau, aber ich glaube, Objekte in den User Defaults sind immer immutable.

    Es ist also keine schlechte Idee, immer eine mutableCopy von diesen Objekten zu machen.

    Vielleicht hilft's?

    Alex
    The only thing that really worried me was the ether.
  • ich habs grad hin bekommen. ich weiss zwar immernoch nicht, warum die erste version nicht funktioniert, aber diese hier tut es:

    Quellcode

    1. - (IBAction)card_change:(id)sender
    2. {
    3. NSMutableArray *card_ids = [NSMutableArray arrayWithArray:[preferences objectForKey:@"card_ids"]];
    4. int i = [card_listPopup indexOfSelectedItem];
    5. [card_ids replaceObjectAtIndex:i withObject:[NSArray arrayWithObjects:[card_id stringValue],[card_name stringValue],[card_address string],nil]];
    6. [preferences setObject:card_ids forKey: @"card_ids"];
    7. [[NSUserDefaults standardUserDefaults] synchronize];
    8. [self reloadCardPopup];
    9. }
    Alles anzeigen


    sascha
  • RE: mutablearry probleme

    Das Problem ist dass es ein Array aus Arrays von Objekten ist...

    Quellcode

    1. [[card_ids objectAtIndex:i] replaceObjectAtIndex:...


    * card_ids ist offenbar ein Array (sonst würde objectAtIndex nicht gehen)
    * [card_ids objectAtIndex:i] müßte ein NSMutableArray sein damit replaceObject geht

    Mit der Initialisierung wird nur das äußere Array zu einer mutable-Kopie - nicht aber die dort gespeicherten Inhalte (Arrays auf zweiter Stufe)!

    Beim zweiten Code wird gleich das ganze Inhalts-Array ersetzt. Das geht dann natürlich.

    -- hns
  • Die erste Variante funktioniert beim zweiten Mal nicht mehr, weil Du aus den UserDefaults nur NSArrays bekommst. Du machst zwar aus dem übergeordneten NSArray ein NSMutableArray, aber die NSArrays "in" diesem NSMutableArray sind weiterhin immutable. Der Objektgraf sieht dann so aus:

    Quellcode

    1. ---> NSArray
    2. |
    3. NSMutableArray -+--> NSArray
    4. |
    5. ---> NSArray
    Michael
  • Stimmt, ein Array ist nämlich ein Dictionary:

    macentwicklerwelt.net/index.php?title=Collections

    Warum es dennoch einen Unterschied macht?

    Was für einen Unterschied macht es, wenn du statt er Variablennamen
    card_ids und i

    einfach
    Variable1 und Variable2

    verwendest? Richtg gar keinen, was die Funktionalität angeht. Richtig, einen riesigen, wenn es um die Lesbarkeit geht. Ob es sich alelrdings lonht, ist eine andere Frage. Zumindest #define solltest du aber verwenden.
    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"?
  • @asarel: enum heißt enumeration - Aufzählung. Jetzt überleg nochmal kurz wegen den Strings und beantworte dir die frage selber.

    @macuser: Wegen dem index und so macht das meines erachtens einen gigantischen unterschied. nehmen wir als beispiel, dass du deine Cards oder was auch immer du da baust als plist speichern willst, damit andere Programme sie importieren können. Woher soll der andere Entwickler wissen, was das erste item ist? Wenn es name heist ist es eindeutig...
    Und ehe jetzt kommt "ich hab doch gar nicht vor..." und "das ist mir viel zu kompiziert..." usw. - ich finde es gehört zu einem guten Programmierstil, Dinge, die sich über keys eindeutig ausdrücken lassen, auch in einem Dictionary zu speichern.
    Und noch was: was, wenn eine karte mal keinen namen hat? oder wenn du mehr attribute hinzufügst, die nicht immer vorhanden sein müssen, wie ein Geburtstag oder so? Bei einem Dictionary ist der key einfach nicht gesetzt, bei einem array, musst du jedoch immer ein leeres objekt oder NSNull einsetzen - das ist nicht gerade das wahre vom ein....

    Max
  • Original von M.A.X

    Quellcode

    1. #define kNameIndex 1

    vielleicht solltest du dich mal mit C beschäftigen, es gibt nichts wichtigeres als die Grundlagen...

    Max


    jetzt weiss ich genausoviel wie vorher....

    natürlich sind grundlagen wichtig. nur ist die frage, ob das noch zu den grundlagen gehört.

    aber davon abgesehen. ich denke das hier ist ein forum in dem man fragen stellen kann,
    aber auf solche antworten kann man gern verzichten. du kannst nicht erwarten, das jeder
    das gleiche oder dein neveau hat. wenn dich die fragen nerven, dan antworte doch einfach
    nicht darauf. aber solche antworten sind nicht wirklich konstruktiv.

    sascha
  • @asarel: enum heißt enumeration - Aufzählung. Jetzt überleg nochmal kurz wegen den Strings und beantworte dir die frage selber.


    Ok, ist auch in Ordnung so, wobei der Begriff "Aufzaehlung" eine Aufzaehlung von Strings nicht ausschliesst.

    Ich hatte die Frage gestellt, weil ich der Meinung war, in C# haette ich sowas schonmal gemacht, war aber doch nicht so, geht auch nicht.
    Ausserdem waere das eine Alternative fuer #defines. Wobei sich natuerlich der Praeprozessor um die textuelle Ersetzung kuemmert, bei enums ist das ja wieder ganz was anderes.

    so long
  • Original von asrael
    enum irgendwas : NSString
    {
    var1 = @"Test1",
    var2 = @"Test2"
    };

    geht sowas?

    Ja, aber andere Syntax:

    Quellcode

    1. NSString *
    2. var1 = @"Test1",
    3. var2 = @"Test2";

    Ein "echter" Enum als Typ 'irgendwas' ist es aber nicht.

    Alternative mit #define:

    Quellcode

    1. #define var1 @"Test1"
    2. #define var2 @"Test2"

    aber 'var' sollte es dann vielleicht nicht mehr heissen sondern eher 'const'.

    Cocoa macht das selbst oft auch so. Z.B. ist die Konstante NSTextDidBeginEditing ein solcher vorbelegter NSString.

    Vorteil des Ganzen: der Compiler prüft Schreibfehler im Variablennamen. Schreibfehler in Konstanten kann er nicht prüfen.

    -- hns
  • Original von macuser
    jetzt weiss ich genausoviel wie vorher....

    #define ist eine so genannte Compilerdirektive, so wie #import zum Beispiel auch. Der Preprozessor verarbeitet sie dann beim bzw. vor dem Compilieren. Was kann man nun mit #define machen? Nun man kann sich Makros definieren. Das simpelste Makro sieht so aus:

    Quellcode

    1. #define MAKRO_NAME makroinhalt

    Wenn Du dann im Code MAKRO_NAME schreibst, dann ersetzt der Preprozessor dies durch makroinhalt. Wozu ist so etwas gut? Ein Beispiel:

    Quellcode

    1. int i;
    2. int feld[10];
    3. for (i = 0; i < 10; i++)
    4. feld[i] = 0;

    Wenn Du bei diesem Code die Größe des Feldes verändern willst, dann musst Du den Code an zwei Stellen ändern. Mit einem Makro lässt sich das auf eine Änderung reduzieren:

    Quellcode

    1. #define MAX 10
    2. int i;
    3. int feld[MAX];
    4. for (i = 0; i < MAX; i++)
    5. feld[i] = 0;

    Außerdem spart man sich das Suchen entsprechender Stellen im Code, da man die Makros sinnvoller Weise am Anfang der Datei bzw. in der Header-Datei definiert.
    Das war jetzt eine ganz simple Anwendung von Makros. Es lassen sich noch viel kompliziertere Dinge damit anstellen.

    Michael