2009-08-27 23 views
11

Tôi có một 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> 

Tôi cố gắng để tải nó thành một NSDictionary như thế này:

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

tôi luôn luôn nhận được một số mảng của 50 nhưng một số từ điển bằng không. Vì vậy, tôi đã cố gắng lặp qua mảng và thêm nó vào từ điển:

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

Nhưng vòng lặp là ném một ngoại lệ:

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

Nhà nước là một lớp học với tính chất phù hợp với tôi plist. Tôi đang làm gì sai? Tôi thấy tất cả các loại câu hỏi liên quan ở đây nhưng tôi không thể có được nó.

+1

tôi đã nhận nó. Tôi đã có một không phù hợp và NsMutableDictionary được phân bổ như là một NSDictionary. – Bryan

+0

Và dĩ nhiên, tôi đã bỏ lỡ nhận xét này cho đến sau khi tôi đăng câu trả lời của mình. – bobDevil

Trả lời

17

Hai vấn đề:

  • Loading the plist vào một NSDictionary:

Đây là một vấn đề đơn giản, mà có vẻ như bạn đã tìm ra. Đối tượng toàn cầu trong plist của bạn là một mảng, không phải là một dict, vì vậy khi bạn tải nó vào từ điển, nó không biết phải làm gì (các loại không tương thích), vì vậy bạn đang nhận được một từ điển trống.

  • Looping thông qua hàng loạt các từ điển:

Từ ngoại lệ bạn đang nhận được, bạn đang gọi 'setObject: forKey:' trên từ điển, mà được khởi tạo như một NSDictionary, không phải là một NSMutableDictionary . Con trỏ được gõ là NSMutableDictionary, nhưng không phải là thực tế trong đối tượng bộ nhớ. Bạn cần phải thay đổi dòng của bạn từ.

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

để

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

và trên thực tế, kể từ khi nạp vào từ điển từ tập tin mang đến cho bạn một từ điển rỗng, bạn đang lãng phí chu kỳ cố gắng để tải nó từ tập tin, và chỉ nên tạo một hình mới :

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

Giải thích tuyệt vời! Điều này sẽ giúp ích rất nhiều cho việc tham khảo trong tương lai. thanks – Bryan

10

Một cách linh hoạt hơn để tải plists vào bộ nhớ, mà còn cho phép bạn tạo plists có thể thay đổi:

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

Như vậy mã của bạn có thể được thực hiện như:

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

errorMô tả đưa ra cảnh báo –

+0

Đối số định dạng là tham số ngoài, vì vậy ví dụ không hoàn toàn đúng ở đây (và sẽ không biên dịch). Ngoài ra, kết quả không nhất thiết là một mảng. Tôi cho là nó có thể, nhưng kết quả cũng có thể là một từ điển, ví dụ.Nói chung, tôi nghĩ rằng đây là một bổ sung tốt cho câu trả lời cho câu hỏi. – wbyoung