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

问题似乎围绕着您工作的深度......您正在创建的容器的可变版本仅适用于该“级别”。您稍后将索引到该级别(即访问更深一层的容器),该级别仍然是不可变的。NSJSONReadingMutableContainers首次反序列化 JSON 时尝试传递该选项:

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