11

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

私はそれを次のような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

2つの問題:

  • plist を NSDictionary にロードする:

これは簡単な問題ですが、すでに理解されているようです。plist のグローバル オブジェクトは辞書ではなく配列であるため、それを辞書にロードすると、何をすべきかわからない (互換性のない型) ため、空の辞書が取得されます。

  • 辞書の配列をループする:

取得している例外から、NSMutableDictionary ではなく NSDictionary として初期化された辞書で「setObject:forKey:」を呼び出しています。ポインターは 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 に答える