Game center 什么是进行GameCenter身份验证的正确方法?

Game center 什么是进行GameCenter身份验证的正确方法?,game-center,Game Center,我在有关堆栈溢出的帖子中看到了处理GameCenter身份验证的片段。然而,这些解决方案都不能解决现实世界用例所涵盖的任何问题。也就是说,[GKLocalPlayer].authenticateHandler只是状态的回调,而不是其他。它提供了一个视图控制器,但在.authenticated和error状态中存在大量不一致 我正在尝试做几件事: 1.在功能使用之前,不要弹出游戏中心登录 2.尝试在应用程序启动时以静默方式进行身份验证 3.向用户提供GameCenter功能失效的原因 4.提供恢复

我在有关堆栈溢出的帖子中看到了处理GameCenter身份验证的片段。然而,这些解决方案都不能解决现实世界用例所涵盖的任何问题。也就是说,[GKLocalPlayer].authenticateHandler只是状态的回调,而不是其他。它提供了一个视图控制器,但在.authenticated和error状态中存在大量不一致

我正在尝试做几件事: 1.在功能使用之前,不要弹出游戏中心登录 2.尝试在应用程序启动时以静默方式进行身份验证 3.向用户提供GameCenter功能失效的原因 4.提供恢复机制

也就是说,如果报告了错误,如何显示登录对话框

我在没有viewController的情况下遇到此错误:

案例1:

GameCenterManager::authenticateLocalPlayer中出错[Internet连接似乎处于脱机状态。]

尽管有错误信息,但该设备完全在线,因为safari可以很好地加载cnn.com

案例2:

有人关闭了登录屏幕,因为他们还没有准备好,在这种情况下。authenticated返回为true,viewController保持为nil,但所有game center调用都将失败。为什么[GKLocalPlayer].authenticated设置为true而不是true

案例3:

GameCenterManager::authenticateLocalPlayer[操作失败]中出错 无法完成。(NSURErrorDomain错误-1009。)]

这一直在发生,但应用程序无法为用户做任何事情。在这种情况下,消息应该是什么?将应用程序切换到游戏中心并登录

案例4:

GameCenterManager::AuthenticateLocalLayer[请求的 用户已取消或禁用操作。]

如果用户取消了应用程序被苹果告知要显示的viewController,就会发生这种情况。然而,也没有恢复或检测到这种状态

案例5:

GameCenterManager::createMatch中出错[请求的操作可能会失败] 无法完成,因为本地玩家尚未通过身份验证。]

如果用户已登录,但出于任何原因退出GameCenter,然后返回应用程序,则会发生这种情况。该应用程序将被告知用户仍然通过了身份验证,但显然没有,但我无法拨打任何电话进行另一次登录

所以从本质上说,如果GameCenter不只是默默地工作,我们作为应用程序设计师该怎么做?警报视图并告诉他们使用游戏中心应用程序登录并重新启动应用程序

这是我的身份验证码:

//******************************************************
// Authenticate
//******************************************************
-(void)authenticateLocalPlayer:(bool)showLogin
{
    if( showLogin && self.loginScreen != nil )
    { [[WordlingsViewController instance] presentViewController:self.loginScreen animated:YES completion:nil]; }

    if( [GKLocalPlayer localPlayer].isAuthenticated )
    {
        NSDLog(NSDLOG_GAME_CENTER,@"GameCenterManager::authenticateLocalPlayer LocalPlayer authenticated");
    }
    __weak GameCenterManager* weakSelf = self;
    [GKLocalPlayer localPlayer].authenticateHandler = ^(UIViewController *viewController, NSError *error)
    {
        if (error != nil)
        {
            NSDLog(NSDLOG_GAME_CENTER,@"Error in GameCenterManager::authenticateLocalPlayer [%@]", [error localizedDescription]);
        }
        else
        {
            if (viewController != nil)
            {
                NSDLog(NSDLOG_GAME_CENTER,@"GameCenter: No authentication error, but we need to login");
                weakSelf.loginScreen = viewController;
            }
            else
            {
                if ( [GKLocalPlayer localPlayer].authenticated )
                {
                    NSDLog(NSDLOG_GAME_CENTER,@"GameCenter localPlayer authenticated");
                    weakSelf.gameCenterAvailable = YES;
                    weakSelf.localPlayer = [GKLocalPlayer localPlayer];
                    [weakSelf retrieveFriends];
                    [weakSelf loadPlayerPhoto:weakSelf.localPlayer];

                    for ( id<GameCenterDelegate> listener in weakSelf.listeners )
                    { [listener onPlayerAuthenticated]; }
                }
                else
                {
                    weakSelf.gameCenterAvailable = NO;
                }
            }
        }
    };
}
//******************************************************
//鉴定
//******************************************************
-(void)authenticateLocalPlayer:(bool)showLogin
{
if(showLogin&&self.loginScreen!=nil)
{[[WordlingsViewController实例]presentViewController:self.loginScreen动画:是完成:nil];}
如果([GKLocalPlayer].isAuthenticated)
{
NSDLog(NSDLog_GAME_CENTER,@“GameCenterManager::authenticateLocalPlayer LocalPlayer authenticated”);
}
__弱GameCenterManager*weakSelf=self;
[GKLocalPlayer localPlayer].authenticateHandler=^(UIViewController*viewController,NSError*error)
{
如果(错误!=nil)
{
NSDLog(NSDLog_GAME_CENTER,@“GameCenterManager中的错误::authenticateLocalPlayer[%@]”,[Error localizedDescription]);
}
其他的
{
if(viewController!=nil)
{
NSDLog(NSDLog_GAME_CENTER,@“GameCenter:没有身份验证错误,但我们需要登录”);
weakSelf.loginScreen=viewController;
}
其他的
{
如果([GKLocalPlayer].localPlayer].authenticated)
{
NSDLog(NSDLog_GAME_CENTER,@“GameCenter本地玩家认证”);
weakSelf.gameCenterAvailable=是;
weakSelf.localPlayer=[GKLocalPlayer localPlayer];
[weakSelf retrieveFriends];
[weakSelf loadPlayerPhoto:weakSelf.localPlayer];
for(weakSelf.listeners中的id侦听器)
{[listener onPlayerAuthenticated];}
}
其他的
{
weakSelf.gameCenterAvailable=否;
}
}
}
};
}

此函数调用两次:一次是在应用程序启动时,希望创建一个有效的登录状态;第二次是在用户未经身份验证且试图使用需要game center的应用程序功能时。在这个应用程序中,它正在创建基于回合的比赛或查看好友

您遇到了许多与我对Game Center API相同的抱怨。我一直在努力实现与你相同的4件事。TL;DR版本:游戏中心根本不支持它但是你可以做一些事情来减轻疼痛

有一点对我有帮助:确保检查
NSError
及其
.underlineerror
属性。我见过几个例子,其中
n错误
太模糊而没有帮助,但是潜在的错误有更具体的细节

案例1:您能否共享NSError和UnderlineingError的错误域和错误代码

案例2:我有一个开放的错误与苹果在这方面,有很长一段时间。有几种情况,包括在飞行模式下,身份验证失败,但
。authenticated
返回true。当我在上面写了一个bug时,苹果关闭了它,说这是“设计的”,所以玩家可以继续使用以前缓存的数据玩游戏。因此,我在bug后面附加了几个场景,其中缓存的数据会导致严重的问题。我的窃听器被重新打开,从那以后一直坐在那里。设计理念似乎是:“好吧,继续前进,也许一切都会在未来实现。”
[localPlayer setAuthenticateHandler:^(UIViewController *loginViewController, NSError *error)
 {
    //this handler is called once when you call setAuthenticated, and again when the user completes the login screen (if necessary)
     VLOGS (LOWLOG, SYMBOL_FUNC_START, @"setAuthenticateHandler completion handler");

     //did we get an error? Could be the result of either the initial call, or the result of the login attempt
     if (error)
     {
         //Here's a fun fact... even if you're in airplane mode and can't communicate to the server,
         //when this call back fires with an error code, localPlayer.authenticated is set to YES despite the total failure. ><
         //error.code == -1009 -> authenticated = YES
         //error.code == 2 -> authenticated = NO
         //error.code == 3 -> authenticated = YES

         if ([GKLocalPlayer localPlayer].authenticated == YES)
         {
             //Game center blatantly lies!
             VLOGS(LOWLOG, SYMBOL_ERROR, @"error.code = %ld but localPlayer.authenticated = %d", (long)error.code, [GKLocalPlayer localPlayer].authenticated);
         }

         //show the user an appropriate alert
         [self processError:error file:__FILE__ func:__func__ line:__LINE__];

         //disable the start button, if it's not already disabled
         [[NSNotificationCenter defaultCenter] postNotificationName:EVENT_ENABLEBUTTONS_NONETWORK object:self ];
         return;
     }

     //if we received a loginViewContoller, then the user needs to log in.
     if (loginViewController)
     {
         //the user isn't logged in, so show the login screen.
         [appDelegate presentViewController:loginViewController animated:NO completion:^
          {
              VLOGS(LOWLOG, SYMBOL_FUNC_START, @"presentViewController completion handler");

              //was the login successful?
              if ([GKLocalPlayer localPlayer].authenticated)
              {
                  //Possibly. Can't trust .authenticated alone. Let's validate that the player actually has some meaningful data in it, instead.
                  NSString *alias = [GKLocalPlayer localPlayer].alias;
                  NSString *name = [GKLocalPlayer localPlayer].displayName;
                  if (alias && name)
                  {
                      //Load our matches from the server. If this succeeds, it will enable the network game button
                      [gameKitHelper loadMatches];
                  }
              }
          }];
     }

     //if there was not loginViewController and no error, then the user is already logged in
     else
     {
         //the user is already logged in, so load matches and enable the network game button
         [gameKitHelper loadMatches];
     }

 }];