11

我有一个列表:

<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>

我正在尝试将它加载到这样的 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]);

我总是得到 50 的数组计数,但字典计数为零。所以我尝试遍历数组并将其添加到字典中:

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

但是循环抛出异常:

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

State 是一个属性与我的 plist 匹配的类。我究竟做错了什么?我在这里看到各种相关的问题,但我无法理解。

4

2 回答 2

17

两个问题:

  • 将 plist 加载到 NSDictionary 中:

这是一个简单的问题,您似乎已经弄清楚了。plist 中的全局对象是一个数组,而不是一个字典,所以当你将它加载到字典中时,它不知道要做什么(不兼容的类型),所以你得到一个空字典。

  • 遍历字典数组:

从您得到的异常中,您正在调用字典上的“setObject:forKey:”,该字典被初始化为 NSDictionary,而不是 NSMutableDictionary。指针类型为 NSMutableDictionary,但不是内存中的实际对象。你需要改变你的线路。

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

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

实际上,由于从文件中加载字典会给您一个空字典,因此您正在浪费周期尝试从文件中加载它,而应该只创建一个新字典:

NSMutableDictionary *myDic = [[NSMutableDictionary alloc] init];
于 2009-08-27T19:18:52.457 回答
10

一种将 plist 加载到内存中的更灵活的方法,它还允许您创建可变 plist:

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

因此,您的代码可以实现为:

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");
}
于 2009-08-28T21:28:50.307 回答