2009-08-27 26 views
11

Ich habe einen plist:Plist Array NSDictionary

<plist version="1.0"> 
    <array> 
    <dict> 
     <key>name</key> 
     <string>Alabama</string> 
     <key>abreviation</key> 
     <string>AL</string> 
     <key>date</key> 
     <string>1819</string> 
     <key>population</key> 
     <string>4,627,851</string> 
     <key>capital</key> 
     <string>Montgomery</string> 
     <key>largestCity</key> 
     <string>Birmingham</string> 
    </dict> 
    <dict> 
     <key>name</key> 
     <string>Alaska</string> 
     <key>abreviation</key> 
     <string>AK</string> 
     <key>date</key> 
     <string>1959</string> 
     <key>population</key> 
     <string>683,478</string> 
     <key>capital</key> 
     <string>Juneau</string> 
     <key>largestCity</key> 
     <string>Anchorage</string> 
    </dict> 
    ... 
    </array> 
</plist> 

ich es in eine NSDictionary wie diese zu laden versuchen:

NSString *path = [[NSBundle mainBundle] pathForResource:@"stateInfo" ofType:@"plist"]; 

NSFileManager *fileManager = [NSFileManager defaultManager]; 
if ([fileManager fileExistsAtPath:path]) { 
    NSLog(@"The file exists"); 
} else { 
    NSLog(@"The file does not exist"); 
} 

NSMutableDictionary *myDic = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; 
//NSDictionary *myDic = [NSDictionary dictionaryWithContentsOfFile:path]; 
NSLog(@"The count: %i", [myDic count]); 

NSArray *thisArray = [[NSArray alloc] initWithContentsOfFile:path]; 
NSLog(@"The array count: %i", [thisArray count]); 

ich immer eine Array Zahl von 50 erhalten, aber eine Wörterbuch Zahl von Null. Also habe ich versucht, durch das Array Looping und es dem Wörterbuch hinzufügen:

NSDictionary *eachState; 
for (eachState in thisArray) { 
    State *thisState = [[State alloc] initWithDictionary:eachState]; 
    [myDic setObject:thisState forKey:thisState.name]; 
} 

Aber die Schleife wirft eine Ausnahme:

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

Staat ist eine Klasse mit Eigenschaften passend zu meiner plist. Was mache ich falsch? Ich sehe hier alle möglichen verwandten Fragen, aber ich verstehe es nicht.

+1

ich es bekam. Ich hatte eine Diskrepanz und NsMutableDictionary wurde als NSDictionary zugewiesen. – Bryan

+0

Und natürlich habe ich diesen Kommentar verpasst, bis ich meine Antwort geschrieben habe. – bobDevil

Antwort

17

Die zwei Probleme:

  • die plist in einem NSDictionary Laden:

Dies ist ein einfaches Problem, das es Sie bereits herausgefunden haben scheint. Das globale Objekt in Ihrem Plist ist ein Array, kein Diktat. Wenn Sie es in das Wörterbuch laden, weiß es nicht, was zu tun ist (nicht kompatible Typen). Sie erhalten also ein leeres Wörterbuch.

  • Looping durch die Anordnung von mehreren Wörterbüchern:

Von der Ausnahme, Sie bekommen, die Sie anrufen ‚setObject: forKey:‘ auf dem Wörterbuch, das als NSDictionary initialisiert wird, nicht ein NSMutableDictionary . Der Zeiger wird als NSMutableDictionary, aber nicht das tatsächliche in Speicherobjekt getippt. Sie müssen Ihre Linie ändern von.

NSMutableDictionary *myDic = [[NSDictionary alloc] initWithContentsOfFile:path]; 

zu

NSMutableDictionary *myDic = [[NSMutableDictionary alloc] initWithContentsOfFile:path]; 

und tatsächlich, da aus der Datei das Wörterbuch Laden Sie ein leeres Wörterbuch gibt, Sie verschwenden Zyklen versuchen, es aus der Datei zu laden, und sollte nur eine neue erstellen :

NSMutableDictionary *myDic = [[NSMutableDictionary alloc] init]; 
+0

Große Erklärung! Dies wird eine große Hilfe für zukünftige Referenz sein. Danke – Bryan

10

Ein flexibler plists in den Speicher zu laden, das es Ihnen ermöglicht auch wandelbar plists zu erstellen:

NSData* data = [NSData dataWithContentsOfFile:path]; 
NSMutableArray* plist = [NSPropertyListSerialization propertyListFromData:data 
                 mutabilityOption:NSPropertyListImmutable 
                    format:NSPropertyListXMLFormat_v1_0 
                 errorDescription:NULL]; 

So könnte Ihr Code implementiert werden, wie:

NSString *path = [[NSBundle mainBundle] pathForResource:@"stateInfo" ofType:@"plist"]; 
NSData* data = [NSData dataWithContentsOfFile:path]; 
NSMutableArray* array = [NSPropertyListSerialization propertyListFromData:data 
                 mutabilityOption:NSPropertyListImmutable 
                    format:NSPropertyListXMLFormat_v1_0 
                 errorDescription:NULL]; 
if (array) { 
    NSMutableDictionary* myDict = [NSMutableDictionary dictionaryWithCapacity:[array count]]; 
    for (NSDictionary* dict in array) { 
    State* state = [[State alloc] initWithDictionary:dict]; 
    [myDict setObject:state forKey:state.name; 
    [state release]; 
    } 
    NSLog(@"The count: %i", [myDic count]); 
} else { 
    NSLog(@"Plist does not exist"); 
} 
+0

errorDescription gibt die Warnung –

+0

Das Format Argument ist ein out-Argument, so das Beispiel ist hier nicht ganz richtig (und wird nicht kompiliert). Außerdem ist das Ergebnis nicht unbedingt ein Array. Ich vermutete, es könnte sein, aber das Ergebnis könnte zum Beispiel auch ein Wörterbuch sein.Insgesamt denke ich, dass dies eine gute Ergänzung zu den Antworten auf die Frage ist. – wbyoung

Verwandte Themen