オフライン モード (機内モードがオンになっているなど) の場合に Game Center で実績を操作するための最良の方法を見つけようとしています。
私の知る限り、iOS 5 以降の Game Center は、オフラインで提出された実績とスコアを処理します。これはプロキシ キャッシュのように機能し、次にユーザーがオンラインになったときにそれらをオンラインの Game Center に送信します。これを考慮して、私は次のことを行います。
ユーザー認証が成功したら、アチーブメントを読み込み、辞書に保存します。
[GKAchievement loadAchievementsWithCompletionHandler:^(NSArray *gcAchievments, NSError *error)
{
if (error) { ..skipped ..}
//This dictionary will store current achievments, so that we didn't submit them
//once more and didn't show notification.
achievments = [[NSMutableDictionary alloc] initWithCapacity:gcAchievments.count];
//Storing achievments in dictionary
for(GKAchievement *a in gcAchievments)
[achievments setObject:a forKey:a.identifier];
}];
後で新しいアチーブメントを提出するとき、辞書でアチーブメントをチェックし、アチーブメントがすでに完了している場合は提出しません。アチーブメントを送信すると、それをachievments
ディクショナリ (メモリ内) にも追加して、このアチーブメントが既に送信されていることをすぐに反映します。
GKAchievement *cachedAchievment = [achievments objectForKey:identifier];
if (cachedAchievment && cachedAchievment.percentComplete >= 100)
{
//Already unlocked this achievment.
return;
}
GKAchievement *achievement = [[GKAchievement alloc] initWithIdentifier: identifier];
if (achievement)
{
achievement.percentComplete = percent;
[achievement reportAchievementWithCompletionHandler:^(NSError *error)
{
if (!error)
{
//Flagging achievment as completed locally to avoid achieving it second time and showing notification.
[achievments setObject:achievement forKey:achievement.identifier];
//Now shoing notification banner.
GKAchievementDescription * desc = [achievmentsDescriptions objectForKey:achievement.identifier];
[[GKAchievementHandler defaultHandler] notifyAchievement:desc];
}
else
{
NSLog(@"Error in reporting achievements: %@", error);
}
}];
}
このアプローチにより、ゲーム コードで送信をトリガーすることができ、アチーブメントを 2 回送信したり、通知バナーを 2 回表示したりすることを心配する必要はありません。
Game Center がオンラインの場合、Everyting は正常に動作します。しかし、オフラインの場合、2 つの問題があります。
コードをロードするとエラーが返され、 の初期ディクショナリに
achievments
はすでに完了したアチーブメントが入力されていません。これは、ユーザーがゲームを起動するたびに、アチーブメントがすでに授与されている場合でも、各アチーブメントの通知バナーを再度受け取ることを意味します。その後、辞書に配置された後は表示されませんが、ゲームの開始ごとに実績を一度も表示したくありません。ユーザーがオンラインになったときに、オフラインで送信された実績が Game Center に届くかどうかはわかりません。永続的なストレージ (データベースなど) を使用してゲームの起動間の達成状況を保存することで問題 #1 を解決できますが、Game Center がオンラインのときにそれらを再送信する必要があります
reportAchievementWithCompletionHandler
。そのため、送信されていないかどうかを検出できません。これが私がテストしている方法です。機内モードをオンにし、いくつかの実績のロックを解除してから機内モードをオフにしました。これは「サンドボックス」の問題かもしれませんが、実績はゲームセンターに届きません.