3

これはかなり一般的な問題のようですが、私が調べた解決策ではエラーは解決されません。JSONファイルからNSMutableArrayを読み取ろうとしています。私が見た提案の多くは、mutableCopyまたは[NSMutableArray arrayWithArray:]の使用を含みますが、以下に示すreplaceObjectAtIndex:withObject:の呼び出しを使用した場合、これらの解決策はどちらも問題を解決しません。この問題を解決する方法について何かアドバイスがあれば教えてください。

編集:インベントリリストがNSMutableArrayオブジェクトのNSMutableArrayであることも追加したいと思います。

正確なエラーは次のとおりです。

Terminating app due to uncaught exception 'NSInternalInconsistencyException', 
reason: '-[__NSCFArray replaceObjectAtIndex:withObject:]: 
mutating method sent to immutable object'

実装ファイルの先頭に次のように定義されたプロパティがあります。

NSMutableArray *inventoryData;

次のようにJSONファイルから読み取ろうとしています。

- (void)readJSON
{
    //Code to get dictionary full of saves from JSON file (overworld.json) - includes the file path on the ipad as well as
    //the dictionary itself
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *localPath = [[NSString alloc] initWithString:[documentsDirectory stringByAppendingPathComponent:@"savedPaintGameData.json"]];
    NSString *filePath = [localPath mutableCopy];
    NSError *e = nil;

    // Read data from file saved previously - read the raw data from the path, then parse it into a dictionary using JSONObjectWithData
    NSData *RawJSON = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:&e];

    if (RawJSON == nil) {
        [self saveGameInitialize];
    } else {
        NSMutableDictionary *localDictionary = [[NSMutableDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:RawJSON options:NSJSONReadingAllowFragments error:&e]];
        NSMutableDictionary *savedDataDictionary = [localDictionary mutableCopy];

        //inventoryData = [[savedDataDictionary objectForKey:@"inventory"] mutableCopy];
        inventoryData = [NSMutableArray arrayWithArray:[savedDataDictionary objectForKey:@"inventory"]];
    }
}

次に、次のように、NSMutableArrayの指定されたインデックスにあるオブジェクトを置き換えようとしています。

- (void)setInventoryData: (NSString *) colorKey: (int) change
{
    // Check if inventory already contains the paint and change the amount
    bool foundPaint = false;
    int newAmount = 100;    // Magic number prevents crashing @ removal check
    for (int i = 0; i < [inventoryData count]; i++) {
        NSMutableArray *object = [inventoryData objectAtIndex:i];
        if ([[object objectAtIndex:0] isEqualToString:colorKey]) {
            newAmount = [[object objectAtIndex:1] integerValue] + change;
            [[inventoryData objectAtIndex:i] replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:newAmount]];
            foundPaint = true;
            break;
        }
    }

    if (newAmount == 0) {
        [self removeInventoryColor:colorKey];
    }
}
4

1 に答える 1

7

問題は、作業している深さを取り巻くようです...作成しているコンテナの可変バージョンは、その「レベル」にのみ適用されます。後で、不変であるそのレベルにインデックスを作成します(つまり、1レベル深いコンテナにアクセスします)。NSJSONReadingMutableContainersJSONを最初に逆シリアル化するときに、オプションを渡してみてください。

NSUInteger jsonReadingOptions = NSJSONReadingAllowFragments | NSJSONReadingMutableContainers;
NSMutableDictionary *localDictionary = [[NSMutableDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:RawJSON options:jsonReadinOptions error:&e]];
于 2012-07-17T19:36:08.233 に答える