Подтвердить что ты не робот

IOS 6 Game Center authenticateHandler не может войти после отмены

При использовании аутентификацииHandler в iOS 6 игровой центр не будет отображать окно входа в систему, если пользователь отменит его. Я понимаю, что игровой центр автоматически блокирует приложение после 3 попыток отмены, но я говорю только о двух попытках. Если они отменили регистрацию, они должны покинуть приложение и вернуться, прежде чем игровой центр представит логин, даже через authenticateHandler снова будет установлен. Любые идеи о том, как обрабатывать этот случай в iOS 6?

Он отлично работает при использовании более старого метода authenticateWithCompletionHandler:

#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_6_0
    GKLocalPlayer.localPlayer.authenticateHandler = authenticateLocalPlayerCompleteExtended;
#else
    [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:authenticateLocalPlayerComplete];
#endif

Причина, по которой это важно для моего приложения, заключается в том, что для него требуется игровой центр для мультиплеер. Приложение пытается аутентифицироваться в игровом центре при запуске, но если пользователь отменяет, мы не будем спрашивать их при запуске снова, чтобы они не пострадали. Что мы делаем - это кнопка входа в Game Center, если они не вошли в систему, когда они выбирают мультиплеер. Кнопка входа в систему заставляет войти в игровой центр, вызвав authenticateWithCompletionHandler (и теперь снова установив GKLocalPlayer.localPlayer.authenticateHandler).

4b9b3361

Ответ 1

Лучше использовать проверки времени выполнения (экземплярыRespondToSelector:) вместо инструкций #if препроцессора, чтобы вы могли использовать рекомендуемые методы, где они доступны и амортизируются в другом месте. Я действительно обнаружил, что перед установкой обработчика приглашения нужно выделить три случая, так как обработчик проверки подлинности также может быть вызван с помощью контроллера представления nil:

 -(void)authenticateLocalPlayer
 {
     if ([[GKLocalPlayer class] instancesRespondToSelector:@selector(setAuthenticateHandler:)]) {
         [[GKLocalPlayer localPlayer] setAuthenticateHandler:^(UIViewController *gameCenterLoginViewController, NSError *error) {
             if (gameCenterLoginViewController) {
                 [self.presentedViewController presentViewController:gameCenterLoginViewController
                                                            animated:YES
                                                          completion:^{
                                                              [self setInviteHandlerIfAuthenticated];
                                                          }];
             } else {
                 [self setInviteHandlerIfAuthenticated];
             }
         }];
     } else { // alternative for iOS < 6
         [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
             [self setInviteHandlerIfAuthenticated];
         }];
     }
 }

В обработчике приглашения должно быть выделено еще больше случаев, так как matchForInvite:: также является новым в iOS6 и позволяет избежать еще одного раунда через контроллеры просмотра игрового центра:

-(void)setInviteHandlerIfAuthenticated
{
    if ([GKLocalPlayer localPlayer].isAuthenticated) {
        [GKMatchmaker sharedMatchmaker].inviteHandler = ^(GKInvite *acceptedInvite, NSArray *playersToInvite) {
            if (acceptedInvite) {
                if ([GKMatchmaker instancesRespondToSelector:@selector(matchForInvite:completionHandler:)]) {
                    [self showInfoAnimating:YES completion:NULL];
                    [[GKMatchmaker sharedMatchmaker] matchForInvite:acceptedInvite
                                                  completionHandler:^(GKMatch *match, NSError *error) {
                                                      // ... handle invited match
                                                  }];
                } else {
                    // alternative for iOS < 6
                    GKMatchmakerViewController *mmvc = [[[GKMatchmakerViewController alloc] initWithInvite:acceptedInvite] autorelease];
                    mmvc.matchmakerDelegate = self;
                    // ... present mmvc appropriately
                    // ... handle invited match found in delegate method matchmakerViewController:didFindMatch:
                 }
            } else if (playersToInvite) {
                 // ... handle match initiated through game center
            }
        };
    }
}

Сообщите мне, если это поможет.

Ответ 2

Я не думаю, что это возможно в iOS 6.0. Были вызовы API для этого в ранних сборках SDK, которые были удалены до выпуска.

В WWDC 2012 Видео: Сессия 516 - Интеграция ваших игр с Game Center [8:30] На самом деле они показывают код, где вы вызываете метод authenticate:

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
localPlayer.authenticationHandler = //handle the callback...
[localPlayer authenticate];

Этот метод теперь является частным API, но вы можете увидеть его в действии, вызвав:

[[GKLocalPlayer localPlayer] performSelector:@selector(_authenticate)];

Он делает именно то, что вы хотите, но не может использоваться, потому что теперь он закрыт.


Вы также можете инициировать процесс аутентификации, отправив уведомление UIApplicationWillEnterForegroundNotification:

[[NSNotificationCenter defaultCenter] postNotificationName:UIApplicationWillEnterForegroundNotification object:[UIApplication sharedApplication]];

Я предполагаю, что было бы нецелесообразно делать это в реальном коде.