2

这是一个奇怪的...

我会定期检查用户是否在我的应用中获得了新的最高分。这是我的代码:

- (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];
    }

}

有时代码工作得很好,无论是对于 if 还是 else。有时虽然我收到以下错误:

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

我尝试设置断点并逐行执行程序。崩溃似乎有些随机,我无法找出模式。一般一秒就崩溃了...

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

...线。

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

任何建议的帮助将不胜感激。

谢谢。

4

2 回答 2

4
[[[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];

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

于 2012-04-18T07:49:40.063 回答
1

NSUserDefaults不存储您为其设置的对象。它存储数据。实际上,它正在复制。您从中检索的任何集合对象NSUserDefaults都是不可变的。

编辑说:另外,当你制作一个集合的可变副本时,它是一个浅拷贝。您将获得一个可变集合,其中包含与原始集合相同的对象。如果原始集合包含不可变对象,那么新集合也将如此。

如果您需要对与属性列表兼容的对象层次结构进行深层复制,获取可变对象,您可以使用NSPropertyListSerialization. 结合+dataWithPropertyList:format:options:error:+propertyListWithData:options:format:error:NSPropertyListMutableContainers选项NSPropertyListMutableContainersAndLeaves

于 2012-04-18T09:06:32.883 回答