错误:改变从JSON文件发送到NSMutableArray不可变对象的方法

时间:2022-09-25 18:44:32

This seems to be a fairly common problem, but the solutions that I have looked at do not solve the error. I am trying to read an NSMutableArray from a JSON file. Many of the suggestions I have seen involve using mutableCopy or [NSMutableArray arrayWithArray:] but both of these solutions do not fix the problem when using the call replaceObjectAtIndex:withObject: seen below. Please let me know if you have any advice on how to solve this problem.

这似乎是一个相当普遍的问题,但是我所看到的解决方案并不能解决错误。我正在尝试从JSON文件中读取NSMutableArray。我看到的许多建议都涉及到使用mutableCopy或[NSMutableArray arrayWithArray:],但这两个解决方案在使用调用replaceObjectAtIndex:withObject:时都没有解决问题。如果你对如何解决这个问题有什么建议,请告诉我。

EDIT: I would also like to add that the inventory list is an NSMutableArray of NSMutableArray objects.

编辑:我还想补充,库存列表是一个NSMutableArray的NSMutableArray对象。

The exact error reads:

确切的错误读取:

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

I have the property defined as follows at the top of my implementation file:

我在实现文件的顶部定义了如下属性:

NSMutableArray *inventoryData;

I am trying to read it from a JSON file as follows:

我正在尝试从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"]];
    }
}

I am then trying to replace an object at the given index of the NSMutableArray as seen here:

然后,我试图在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];
    }
}

1 个解决方案

#1


7  

The issue appears to be surround the depth at which you are working... the mutable versions of containers you are creating only apply to that "level". You are later indexing into that level (i.e. accessing a container one level deeper) which is still immutable. Try passing the NSJSONReadingMutableContainers option when you first unserialize the JSON:

问题似乎在于你工作的深度……您正在创建的容器的可变版本仅适用于该“级别”。稍后您将索引到该级别(即访问容器更深一层),该级别仍然是不可变的。当您第一次卸载JSON时,尝试传递NSJSONReadingMutableContainers选项:

NSUInteger jsonReadingOptions = NSJSONReadingAllowFragments | NSJSONReadingMutableContainers;
NSMutableDictionary *localDictionary = [[NSMutableDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:RawJSON options:jsonReadinOptions error:&e]];

#1


7  

The issue appears to be surround the depth at which you are working... the mutable versions of containers you are creating only apply to that "level". You are later indexing into that level (i.e. accessing a container one level deeper) which is still immutable. Try passing the NSJSONReadingMutableContainers option when you first unserialize the JSON:

问题似乎在于你工作的深度……您正在创建的容器的可变版本仅适用于该“级别”。稍后您将索引到该级别(即访问容器更深一层),该级别仍然是不可变的。当您第一次卸载JSON时,尝试传递NSJSONReadingMutableContainers选项:

NSUInteger jsonReadingOptions = NSJSONReadingAllowFragments | NSJSONReadingMutableContainers;
NSMutableDictionary *localDictionary = [[NSMutableDictionary alloc] initWithDictionary:[NSJSONSerialization JSONObjectWithData:RawJSON options:jsonReadinOptions error:&e]];