2009-08-27 20 views
11

Mam plist:PLIST Array do 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> 

próbuję go załadować do w NSDictionary tak:

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]); 

zawsze uzyskać liczbę tablicy 50, lecz słownika count zero. Dlatego starałem zapętlenie za pośrednictwem tablicy i dodanie go do słownika:

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

Ale pętla rzuca wyjątek:

State

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

jest klasa z właściwości dopasowania mój plist. Co ja robię źle? Widzę tu wszystkie powiązane pytania, ale nie mogę tego dostać.

+1

mam. Miałem niezgodność i NsMutableDictionary został przydzielony jako NSDictionary. – Bryan

+0

I oczywiście tęskniłem za tym komentarzem, dopóki nie napisałem swojej odpowiedzi. – bobDevil

Odpowiedz

17

Dwa problemy:

  • załadowaniu plist się z NSDictionary:

Jest to prosty problem, który wydaje się już zorientowali się. Globalny obiekt w twoim plist jest tablicą, a nie dyktatem, więc kiedy ładujesz ją do słownika, nie wie, co robić (typy niekompatybilne), więc dostajesz pusty słownik.

  • pętli w tablicy słowników:

z wyjątku dostajesz, dzwonisz „setObject: forKey:” w słowniku, który jest inicjowany jako NSDictionary, a nie NSMutableDictionary . Wskaźnik jest wpisany jako NSMutableDictionary, ale nie faktyczny w obiekcie pamięci. Musisz zmienić swoją linię z.

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

do

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

i rzeczywiście, od momentu załadunku słownika z pliku daje pusty słownik, tracisz cykli próbuje załadować go z pliku i należy po prostu utworzyć nowy :

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

Świetne wyjaśnienie! Będzie to bardzo pomocne w przyszłości. dzięki – Bryan

10

bardziej elastyczny sposób, aby załadować listy właściwości do pamięci, która pozwala również na tworzenie listy właściwości zmienne:

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

Tak więc kod może być realizowane jako:

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 daje ostrzeżenie –

+0

Argument format jest argumentem zewnętrznym, więc przykład nie jest tu całkiem odpowiedni (i nie będzie kompilowany). Ponadto wynik niekoniecznie musi być tablicą. Przypuszczam, że tak, ale rezultatem może być na przykład słownik.Ogólnie rzecz biorąc, uważam, że jest to dobry dodatek do odpowiedzi udzielonych na pytanie. – wbyoung