这是一个奇怪的......
我正在检查用户是否在我的应用中获得了新的最高分。这是我的代码:
- (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"];
...线。
对象是可变的。或者至少它是。为什么会改变?
非常感谢任何建议的帮助。
感谢。
答案 0 :(得分:4)
[[[mutableBoardsAndScores objectAtIndex:gameBoardIndex] mutableCopy] setObject:topscoreString forKey:@"topscore"];
你能测试一下吗? (为gameBoard添加了mutableCopy);
修改强>
你可以将上面改为:
NSMutableArray *gameBoard = [[mutableBoardsAndScores objectAtIndex:gameBoardIndex] mutableCopy];
[gameBoard setObject:topscoreString forKey:@"topscore"];
[mutableBoardsAndScores removeObjectAtIndex:gameBoardIndex];
[mutableBoardsAndScores insertObject:gameBoard atIndex:gameBoardIndex];
你可以尝试一下吗?它可能不是最美丽的解决方案,但我相信它会起作用。
答案 1 :(得分:1)
NSUserDefaults
不会存储您为其设置的对象。它存储数据。实际上,它正在制作副本。 <{1}}中检索的任何集合对象都是不可变的。
编辑说:另外,当你制作一个可变的集合副本时,它是一个浅层副本。您获得一个可变集合,其中包含与原始集合相同的对象。如果原始集合持有不可变对象,那么新集合也将如此。
如果需要对属性列表兼容的对象层次结构进行深层复制,将可变对象恢复,则可以使用NSUserDefaults
。将NSPropertyListSerialization
与+dataWithPropertyList:format:options:error:
和+propertyListWithData:options:format:error:
或NSPropertyListMutableContainers
选项合并。