将对象添加到一个可变的阵列时,奇怪的“突变方法发送到不可变的对象”错误(Strange “mutat

2019-09-16 14:17发布

这是一个奇怪的一个...

定期,如果用户已经在我的应用程序实现了新的最高分我检查。 这里是我的代码:

- (void) newTopScore
{
    // pull old top score from the database
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSDictionary *getBoardsAndScores = [defaults dictionaryRepresentation];
    NSMutableArray *boardsAndScores = [[getBoardsAndScores objectForKey:@"boardsAndScores"] mutableCopy];
    NSMutableDictionary *boardAndScoreObject = [[boardsAndScores objectAtIndex:gameBoardIndex] mutableCopy];
    NSString *topscore = [boardAndScoreObject objectForKey:@"topscore"];  

    NSLog(@"topscore in value: %i", [topscore intValue]);

    if ([topscore intValue] == 0)
    {
        NSString *topscoreString = [[NSString alloc] initWithFormat:@"%i", [self countCurrentPegs]];

        NSMutableArray *mutableBoardsAndScores = [boardsAndScores mutableCopy];

        [[mutableBoardsAndScores objectAtIndex:gameBoardIndex] setObject:topscoreString forKey:@"topscore"];

        [defaults setObject:mutableBoardsAndScores forKey:@"boardsAndScores"];
        [defaults synchronize];

    }

    else if ([self countCurrentPegs] < [topscore intValue])
    {
        NSString *topscoreString = [[NSString alloc] initWithFormat:@"%i", [self countCurrentPegs]];

        NSMutableArray *mutableBoardsAndScores = [boardsAndScores mutableCopy];

        [[mutableBoardsAndScores objectAtIndex:gameBoardIndex] setObject:topscoreString forKey:@"topscore"];

        [defaults setObject:mutableBoardsAndScores forKey:@"boardsAndScores"];
        [defaults synchronize];
    }

}

有时,代码工作得很好,既为,如果和别的。 虽然有时我得到以下错误:

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

我试着设置断点,并通过线的程序行步进。 崩溃似乎有点随机,我不能制定出一个模式。 它通常会崩溃的第二...

[[mutableBoardsAndScores objectAtIndex:gameBoardIndex] setObject:topscoreString forKey:@"topscore"];

...线。

对象是可变的。 或者至少这是。 为什么变化?

建议的任何帮助将是非常赞赏。

谢谢。

Answer 1:

[[[mutableBoardsAndScores objectAtIndex:gameBoardIndex] mutableCopy] setObject:topscoreString forKey:@"topscore"];

你可以测试这个? (添加的mutableCopy为游戏键盘);

编辑

你可以改变上面:

NSMutableArray *gameBoard = [[mutableBoardsAndScores objectAtIndex:gameBoardIndex] mutableCopy];

[gameBoard setObject:topscoreString forKey:@"topscore"];

[mutableBoardsAndScores removeObjectAtIndex:gameBoardIndex];
[mutableBoardsAndScores insertObject:gameBoard atIndex:gameBoardIndex];

你可以试试这个? 它可能不是最漂亮的解决方案,但我相信它会工作。



Answer 2:

NSUserDefaults不存储你设置它的对象。 它存储的数据。 实际上,它使一个副本。 你从任何检索集合对象NSUserDefaults将是不可改变的。

编辑说:还,当你收集的可变副本,这是一个浅拷贝。 你得到一个可变集合抱着同一对象的原始集合。 如果原来的集合持有的不可变对象,那么所以将新的集合。

如果你需要做的对象的属性列表互换层次结构的深层副本,获得可变对象回来了,你可以使用NSPropertyListSerialization 。 结合+dataWithPropertyList:format:options:error:+propertyListWithData:options:format:error:NSPropertyListMutableContainersNSPropertyListMutableContainersAndLeaves选项。



文章来源: Strange “mutating method sent to immutable object” error when adding an object to a mutable array