iOS 6 Game Center authenticateHandler 取消后无法登录

Posted

技术标签:

【中文标题】iOS 6 Game Center authenticateHandler 取消后无法登录【英文标题】:iOS 6 Game Center authenticateHandler can't login after a cancel 【发布时间】:2012-10-13 04:47: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)来强制登录游戏中心。

【问题讨论】:

听起来你已经这样做了,但是调用 [[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:nil] 将导致再次使用身份验证视图控制器调用 authenticateHandler。虽然在 iOS6 中已弃用此方法。 我正在使用 depreciated 调用来使其工作,但我正在寻找不使用 deprecated 调用的“正确”方法来执行此操作。我尝试将新的 GKLocalPlayer.localPlayer.authenticateHandler 设置为 nil,然后返回到我的处理程序以查看是否可行,并尝试将其设置为 nil 时出现异常。我没有尝试将其设置为不同的处理程序以查看是否会触发登录(这看起来真的很hacky) 我尝试将处理程序切换到另一个处理程序,这也不会触发新的登录对话框打开。我在开发者论坛上发帖,看看是否有人有任何建议,如果我有任何意见,我会在这里发帖。 devforums.apple.com/message/744983 这方面有什么更新吗?我有一个“加载”屏幕,他们必须在其中进行身份验证,所以我只想要一个按钮来再次拉起它。现在我只给我们一个 ivar 并提醒他们。 仍然没有更新。听起来大多数人都使用 depreciated 调用来解决这个问题。 【参考方案1】:

最好使用运行时检查 (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
            
        ;
    

如果这有帮助,请告诉我。

【讨论】:

预处理器宏仅用于调试和显示问题。我遇到的问题是,如果用户取消 Game Center 显示的初始登录,您将无法使用 iOS 6 公共 API 触发登录。 ios6 之前的 API 通过重置处理程序来支持这种行为。【参考方案2】:

我认为这在 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]];

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

【讨论】:

以上是关于iOS 6 Game Center authenticateHandler 取消后无法登录的主要内容,如果未能解决你的问题,请参考以下文章

iOS 开发:验证 Game Center 用户的奇怪问题

iOS 6 中的 Game Center 出现问题

iOS 6 Game Center 在身份验证时崩溃

iOS 6 Game Center authenticateHandler取消后无法登录

iOS 6 Game Center authenticateHandler 取消后无法登录

使用 Xcode 6.0.1 构建后,Game Center 无法识别应用程序