objective-c Plist 数组到 NSDictionary
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1343121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Plist Array to NSDictionary
提问by Bryan
I have a plist:
我有一个 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>
I am trying to load it into an NSDictionary like this:
我正在尝试将它加载到这样的 NSDictionary 中:
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]);
I always get an array count of 50 but a dictionary count of zero. So I tried looping through the array and adding it to the dictionary:
我总是得到 50 的数组计数,但字典计数为零。所以我尝试遍历数组并将其添加到字典中:
NSDictionary *eachState;
for (eachState in thisArray) {
State *thisState = [[State alloc] initWithDictionary:eachState];
[myDic setObject:thisState forKey:thisState.name];
}
But the loop is throwing an exception:
但是循环抛出异常:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '*** -[NSCFDictionary setObject:forKey:]: mutating method sent to immutable object'
State is a class with properties matching my plist. What am I doing wrong? I see all kinds of related questions out here but I can't get it.
State 是一个属性与我的 plist 匹配的类。我究竟做错了什么?我在这里看到各种相关的问题,但我无法理解。
回答by bobDevil
The two problems:
两个问题:
- Loading the plist into an NSDictionary:
- 将 plist 加载到 NSDictionary 中:
This is a simple problem, which it seems you have already figured out. The global object in your plist is an array, not a dict, so when you load it into the dictionary, it doesn't know what to do (incompatable types), so you're getting an empty dictionary.
这是一个简单的问题,您似乎已经想通了。plist 中的全局对象是一个数组,而不是一个 dict,因此当您将其加载到字典中时,它不知道要做什么(不兼容的类型),因此您得到的是一个空字典。
- Looping through the array of dictionaries:
- 遍历字典数组:
From the Exception you're getting, you are calling 'setObject:forKey:' on the dictionary, which is initialized as an NSDictionary, not an NSMutableDictionary. The pointer is typed as NSMutableDictionary, but not the actual in memory object. You need to change your line from.
从你得到的异常中,你在字典上调用“setObject:forKey:”,它被初始化为一个 NSDictionary,而不是一个 NSMutableDictionary。指针类型为 NSMutableDictionary,但不是内存中的实际对象。你需要改变你的线路。
NSMutableDictionary *myDic = [[NSDictionary alloc] initWithContentsOfFile:path];
to
到
NSMutableDictionary *myDic = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
and actually, since loading the dictionary from the file gives you an empty dictionary, you are wasting cycles trying to load it from the file, and should just create a new one:
实际上,由于从文件加载字典会给你一个空字典,你正在浪费试图从文件加载它的周期,应该创建一个新的:
NSMutableDictionary *myDic = [[NSMutableDictionary alloc] init];
回答by PeyloW
A more flexible way to load plists into memory, that also allows you to create mutable plists:
一种将 plist 加载到内存中的更灵活的方法,它还允许您创建可变 plist:
NSData* data = [NSData dataWithContentsOfFile:path];
NSMutableArray* plist = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:NSPropertyListXMLFormat_v1_0
errorDescription:NULL];
Thus your code could be implemented as:
因此,您的代码可以实现为:
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");
}

