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'

ブレークポイントを設定し、プログラムを1行ずつステップ実行してみました。クラッシュはややランダムに見え、パターンを理解できません。通常、2番目にクラッシュします...

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

...ライン。

オブジェクトは変更可能です。または少なくともそうでした。なぜ変わるのですか?

アドバイスをいただければ幸いです。

ありがとう。

4

2 に答える 2

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

これを試していただけますか?それは最も美しい解決策ではないかもしれませんが、うまくいくと信じています。

于 2012-04-18T07:49:40.063 に答える
1

NSUserDefaults設定したオブジェクトは保存されません。データを格納します。事実上、それはコピーを作成しています。また、取得するコレクション オブジェクトはNSUserDefaults不変になります。

言うように編集: また、コレクションの変更可能なコピーを作成すると、それは浅いコピーになります。元のコレクションと同じオブジェクトを保持する変更可能なコレクションを取得します。元のコレクションが不変オブジェクトを保持していた場合、新しいコレクションも同様です。

オブジェクトのプロパティ リストと互換性のある階層のディープ コピーを作成し、変更可能なオブジェクトを取得する必要がある場合は、 を使用できますNSPropertyListSerialization。およびまたはオプション+dataWithPropertyList:format:options:error:と組み合わせます。+propertyListWithData:options:format:error:NSPropertyListMutableContainersNSPropertyListMutableContainersAndLeaves

于 2012-04-18T09:06:32.883 に答える