26

在 iOS 6 中使用 authenticateHandler 时,如果用户取消它,游戏中心将不会显示登录视图。我意识到游戏中心会在 3 次取消尝试后自动锁定应用程序,但我说的只是 2 次尝试。如果他们取消登录,他们必须离开应用程序并在游戏中心显示登录之前返回,即使再次设置了 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 进行多人游戏。该应用程序会在启动时尝试向游戏中心进行身份验证,但如果用户取消,我们不会在启动时再次询问他们,这样他们就不会被唠叨。如果他们在选择多人游戏时没有登录,我们所做的是显示一个 Game Center 登录按钮。登录按钮通过调用 authenticateWithCompletionHandler(现在再次设置 GKLocalPlayer.localPlayer.authenticateHandler)来强制登录游戏中心。

4

2 回答 2

2

更好地使用运行时检查 (instancesRespondToSelector:) 而不是预处理器 #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
            }
        };
    }
}

让我知道这是否有帮助。

于 2013-05-07T08:38:00.620 回答
0

我认为这在 iOS 6.0 中是不可能的。在早期的 SDK 版本中执行此操作的 API 调用在发布之前已被删除。

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

我认为在实时代码中这样做是不可取的。

于 2013-05-29T07:32:42.993 回答