2016-06-03 6 views
0

Was fehlt mir ...?setObject: forKey: mutierende Methode an unveränderliches Objekt gesendet

an anderer Stelle in meinem Projekt gibt es Code wie folgt:

let allUsers = ["userName":["difficulty": 1, "highscore": 50],"userName2":["difficulty": 2, "highscore: 75]]   
defaults.setObject(allUsers, forKey: "allUsers") 

ich einen Wert für einen Benutzer in diesem Array von Benutzern geändert werden soll:

var allUsers = defaults.objectForKey("allUsers") as! [String:NSMutableDictionary] 

let changingUser = allUsers["userName"]! as NSMutableDictionary 

Keines dieser funktioniert:

changingUser.setObject(3, forKey: "difficulty") 
changingUser["difficulty"] = 3 

mit dem Fehler:

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

+5

Die von 'objectForKey' zurückgegebenen Objekte sind unveränderbar. Sie können ein unveränderliches Wörterbuch nicht einfach in ein veränderbares Wörterbuch abwandeln. Sie müssen ein neues NSMutableArray aus dem Array erstellen, das von den Benutzerstandards zurückgegeben wurde, dieses ändern und dann zurückschreiben. – Paulw11

+0

Sie könnten auch zunächst allUsers eingeben, zum Beispiel 'allUsers: [String: NSMutableDictionary] = ...'. Ihre Umwandlung in NSMutableDictionary wäre zu diesem Zeitpunkt korrekt. – Wyatt

Antwort

1

Sie können nicht einfach eine NSDictionary an eine NSMutableDictionary übertragen. Man kann einen initialisieren, indem man ein unveränderliches Gegenstück eingibt, aber das ist leider keine tiefgreifende veränderbare Struktur.

aber Sie können warf es auf einen Swift-Wörterbuch und Zuweisen zu einem var:

var allUsers = defaults.objectForKey("allUsers") as? [String: [String: Int]] ?? [:] 
allUsers2["userName"]?["difficulty"] = 3 

Aber beachten Sie, dass Swift Wörterbücher sind Wertobjekte und haben Wert Semantik. Das heißt, wenn Sie dies in den Schritten tun, wie so:

var allUsers = defaults.objectForKey("allUsers") as? [String: [String: Int]] ?? [:] 
changingUser = allUsers["userName"] 
changingUser?["difficulty"] = 3 //mutates a copy 

Das wird nicht funktionieren, da changingUser eine Kopie ist und während es zu schreiben, tut es mutiert, ist es nicht das allUsers Wörterbuch nicht mutieren. Sie müssen also entweder das geänderte innere Diktat wieder in das äußere Diktat schreiben oder tun, was ich oben getan habe.

+0

So überprüft es, ob allUsers ein [String: [String: Int]] ist und wenn nicht dann [:] was macht? setzt es einfach auf ein Array von AnyObjects? In meinem Fall wird es immer [String: [String: Int]] sein. Vielen Dank! – RanLearns

+0

Nein, das Typsystem garantiert, dass eine gegebene Variable (oder Konstante) immer einen konsistenten Typ hat. Also das ?? part ist ein Standardwert für die Umwandlung, der ein leeres Dictionary zurückgibt, aber immer noch vom Typ '[String: [String: Int]]' –

Verwandte Themen