mutating method sent to immutable object

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • mutating method sent to immutable object

    Ich habe hier ein seltsames Verhalten in meinem Ablauf.
    Ich meine, das ging auch schon mal, bin mir aber nicht mehr sicher...

    Kurze Erklärung:

    An einer Stelle im Programm lese ich Uferdefaults in ein Array ein

    Quellcode

    1. ​ app.scoreArray = [[NSUserDefaults standardUserDefaults] valueForKeyPath:@"appScoreArray"];


    scoreArray ist mutable :

    Quellcode

    1. ​@property (nonatomic, strong) NSMutableArray *scoreArray;


    aus dem Array hole ich an einer anderen Stelle ein Dict zur Bearbeitung raus:

    Quellcode

    1. ​scoreDict = (NSMutableDictionary *)[app.scoreArray objectAtIndex:bahn-1];


    Im Debugger sieht alles gut aus:

    Quellcode

    1. scoreDict NSMutableDictionary * 7 key/value pairs 0x14e40970

    und es sind auch sinnvolle Daten drin

    Quellcode

    1. ​Printing description of scoreDict:
    2. {
    3. kPutts = 2;
    4. kSand = 0;
    5. kScore = 4;
    6. kStableford = 3;
    7. kStraf = 0;
    8. kTee = 0;
    9. kVorgabe = 1;
    10. }


    dann will ich ein Wert ändern:

    Quellcode

    1. ​ [scoreDict setObject:[NSNumber numberWithInt:[self.scoreLabel.text intValue]] forKey:@"kScore"];


    und bekomme einen AppSturz:
    Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'

    es wird kein Problem sein, das anders zu lösen und das Programm ohne Absturz zum Laufen zu bringen.

    Aber ich würde gerne verstehen, was da passiert????
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


    Hape42
  • nussratte schrieb:

    Was du aus deinen userdefaults holst ist kein mutable.

    Jetzt muss ich zu meinem Verständnis nachfragen: Wie (und vor allem warum) unterscheiden die UserDefaults zwischen mutable und immutable Objekten? Ich habe diesbezüglich ehrlich gesagt noch nie z. B. in den PLISTs nachgeschaut, aber der Sinn dieser Unterscheidung beim Persistieren ist mir unklar...

    Mattes

    Edit: Will sagen: Ist das Object aus NSDefaults nicht immer immutable?
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • die antwort wurde schon gegeben.
    hier noch eine erklärung:
    nur weil du du einen setter, getter und iVar hast welche ein NSMutableArray erwarten kannst du jedes objekt damit verwenden solange es auf (id) gecastet wird.
    Und valueForKeyPath liefert eben (id) - was auch sonst.
    Würdest du (wie es korrekt wäre) arrayForKey verwenden, so wüsste der compiler dass er den setter nicht verwenden kann und würde dich warnen.
  • MyMattes schrieb:

    nussratte schrieb:

    Was du aus deinen userdefaults holst ist kein mutable.

    Jetzt muss ich zu meinem Verständnis nachfragen: Wie (und vor allem warum) unterscheiden die UserDefaults zwischen mutable und immutable Objekten? Ich habe diesbezüglich ehrlich gesagt noch nie z. B. in den PLISTs nachgeschaut, aber der Sinn dieser Unterscheidung beim Persistieren ist mir unklar...

    Mattes

    Edit: Will sagen: Ist das Object aus NSDefaults nicht immer immutable?


    edit: steht ja sogar in der doku dass es immer immutable ist (zumindest bei der korrekten methode).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von gritsch ()

  • Vielen Dank für die Antworten. :thumbsup:

    Wenn ich das richtig verstanden habe, liegt das Problem schon beim Auslesen der UserDefaults in das Array.

    ich muss das Array aber bearbeiten können, also brauche ich das "irgendwie" mutable.

    ich werde mir morgen mal "addObjectFromArray" anschauen und meine Lösung hier auch kurz posten (sicher passiert das nicht nur mir :saint: )
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


    Hape42
  • gritsch schrieb:

    du brauchst dir doch nur eine mutable kopie davon machen. Zb mit "mutableCopy".
    das ergebnis musst du dann natülrich nach dem bearbeiten wieder in die userdefaults sichern.


    Du meinst so:?

    Quellcode

    1. ​ NSMutableArray *tmpArray = [[NSMutableArray alloc] initWithCapacity:18];
    2. tmpArray = [[NSUserDefaults standardUserDefaults] valueForKeyPath:@"appScoreArray"];
    3. app.scoreArray = [tmpArray mutableCopy];


    funktioniert leider auch nicht, gleiche Meldung beim Absturz...
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


    Hape42
  • MyMattes schrieb:

    Nein, tmpArray soll immutable sein, also ein Objekt der Klass " NSArray"...

    Mattes


    ?

    edit:
    Achso, du meintest dass er "NSArray" schreibt anstelle von "NSMutableArray"?
    Im Prinzip ist ja egal ob er "id", NSArray, NSString oder NSSet dort hin schreibt. er kann sich so oder so nicht sicher sein was aus den defaults raus kommt.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von gritsch ()

  • Quellcode

    1. ​ NSArray *tmpArray = [[NSArray alloc] init];
    2. tmpArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"appScoreArray"];
    3. app.scoreArray = [tmpArray mutableCopy];


    immer noch gleicher Absturz

    werd mal drüber schlafen ;(
    Ich habe auch keine Loesung, aber ich bewundere das Problem!
    _____________________________________________________


    Hape42
  • hape42 schrieb:

    Quellcode

    1. NSArray *tmpArray = [[NSArray alloc] init];
    2. tmpArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"appScoreArray"];
    3. app.scoreArray = [tmpArray mutableCopy];


    immer noch gleicher Absturz

    werd mal drüber schlafen ;(


    die allloc-init zeite ist immer noch umsonst bis falsch.

    du hast nur das array mutable gemacht, jedoch nicht die dictionaries die im array drin sind. somit kannst du das auch nicht verändern ohne es zuerst mutable zu machen.
  • Alternativ: (Punktnotation. Arghl.)

    Quellcode

    1. NSArray *tmpArray = [[NSUserDefaults standardUserDefaults] arrayForKey:@"appScoreArray"];
    2. NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:tmpArray];
    3. app.scoreArray = mutableArray;


    Oder, entsprechend zusammengekürzt:

    Quellcode

    1. // Mit MutableCopy:
    2. app.scoreArray = [[[NSUserDefaults standardUserDefaults] arrayForKey:@"appScoreArray"] mutableCopy];
    3. // Mit NSMutableArray:
    4. app.scoreArray = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] arrayForKey:@"appScoreArray"]];
    «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
  • Das im Array enthaltene Dictionary ist dann aber auch nicht mutable.
    Somit besteht sein Problem weiterhin, insofern ich den Sinn mit dem obigen Code-Beispiel verstanden habe.

    Im Internet gibt es dazu viel Komisches mit Schleifen und rekursive Aufrufe.
    Dabei ist es so einfach mit NSPropertyListSerialization und der Option NSPropertyListMutableContainersAndLeaves.

    Schreibe Dir doch einfach eine Kategorie zu dem Zeugs.

    Ausserdem mal angedeutet:
    Sind die UserDefaults wirklich die richtige Stelle dafür?
    Ist es vielleicht nicht sinnvoller mit einem Controller zu arbeiten, als über das AppDelegate?

    Dort könntest Du dann schön eine -write… und -read… Methode implementieren, die das alles korrekt handhaben.

    Viele Grüße
  • Stimmt, da habe ich mich zu sehr vom Array ablenken lassen – dabei soll das ja gar nicht verändert werden.
    Muss es aber, wenn anstelle des unveränderlichen Dictionaries ein verändertes Dictionary da rein flattern soll.

    Es sieht auch für mich eher nach einem speicherwürdigen Objekt aus denn nach Benutzereinstellungen.

    Die Option NSPropertyListMutableContainersAndLeaves war mir bis dato unbekannt, vielen Dank dafür! :)
    «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