Array plist a NSDictionary
-
20-09-2019 - |
Domanda
Ho un plist:
<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>
Sto cercando di caricarlo in un NSDictionary in questo modo:
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]);
ottengo sempre un conteggio serie di 50, ma un conteggio dizionario pari a zero. Così ho provato il ciclo attraverso l'array e l'aggiunta al dizionario:
NSDictionary *eachState;
for (eachState in thisArray) {
State *thisState = [[State alloc] initWithDictionary:eachState];
[myDic setObject:thisState forKey:thisState.name];
}
Ma il ciclo è un'eccezione:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
State è una classe con proprietà corrispondenti mia plist. Che cosa sto facendo di sbagliato? Vedo tutti i tipi di domande relative qui fuori, ma io non riesco a farlo.
Soluzione
I due problemi:
- Caricamento del plist in un NSDictionary:
Questo è un problema semplice, che a quanto pare si è già capito. L'oggetto globale nel plist è un array, non un dict, in modo che quando lo si carica nel dizionario, non sa cosa fare (tipi incompatibili quanto), in modo che stai ricevendo un dizionario vuoto.
- Looping attraverso la serie di dizionari:
Dal eccezione che stai ricevendo, si sta chiamando 'setObject: Forkey:' sul dizionario, che viene inizializzata come NSDictionary, non un NSMutableDictionary. Il puntatore è tipizzata come NSMutableDictionary, ma non l'effettivo oggetto di memoria. È necessario modificare la linea da.
NSMutableDictionary *myDic = [[NSDictionary alloc] initWithContentsOfFile:path];
a
NSMutableDictionary *myDic = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
e in realtà, dal momento che il caricamento del dizionario dal file ti dà un dizionario vuoto, si sta sprecando cicli cercando di caricarlo dal file, e dovrebbe solo crearne uno nuovo:
NSMutableDictionary *myDic = [[NSMutableDictionary alloc] init];
Altri suggerimenti
Un modo più flessibile per caricare plists nella memoria, che permette anche di creare plists mutevoli:
NSData* data = [NSData dataWithContentsOfFile:path];
NSMutableArray* plist = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:NSPropertyListXMLFormat_v1_0
errorDescription:NULL];
In questo modo il codice potrebbe essere implementata come:
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");
}