iOS6 上的 GKLocalPlayer 身份验证崩溃并出现模态转换错误

Posted

技术标签:

【中文标题】iOS6 上的 GKLocalPlayer 身份验证崩溃并出现模态转换错误【英文标题】:GKLocalPlayer Auth Crash on iOS6 with Modal Transition Error 【发布时间】:2012-09-25 23:05:07 【问题描述】:

我的应用会记录它是否成功通过 Game Center 的身份验证。当它开始一个新游戏或当用户查看分数列表时,如果本地玩家没有成功验证,并且如果应用程序当时没有尝试验证用户,它会再次尝试.

(为什么?如果您从无网络区域移动到网络区域。)

不幸的是,在 ios6/XCode 4.5 下,它开始崩溃。或者至少在某些有限的情况下似乎是这样:当用户使用错误的密码和/或不存在的帐户无法登录时。成功登录后,一切正常。

在那次不成功的登录之后,当我去做一些导致重新验证检查发生的事情时,我得到这个:

2012-09-25 15:54:47.829 应用程序名称 [1493:907] * -[UIWindowController 中的断言失败 过渡:从视图控制器:到视图控制器:目标:didEndSelector:], /SourceCache/UIKit/UIKit-2372/UIWindowController.m:211

然后这实际上崩溃了:

2012-09-25 15:55:25.569 应用程序名称 [1493:907] * 由于未捕获的异常而终止应用程序 'NSInternalInconsistencyException',原因:'试图开始一个 从 转换时 已经在进行中。等待 viewDidAppear/viewDidDisappear 知道 当前的过渡已完成' * 第一次抛出调用栈:(0x394932a3 0x31db297f 0x3949315d 0x383fd2af 0x3640377b 0x36402fcf 0x394969c4 0x393edfeb 0x36521733 0x32a83d2d 0x3264b11f 0x3264a4b7 0x3264f1bd 0x39466f3b 0x393d9ebd 0x393d9d49 0x353132eb 0x3636b301 0x7e863 0x7e808) libc++abi.dylib: 终止称为抛出异常

这是麻烦的代码:

-(void)authenticateLocalUser 

    if (!self.checkingLocalPlayer) 
        self.checkingLocalPlayer = YES;
        GKLocalPlayer *thisPlayer = [GKLocalPlayer localPlayer];

        if (!thisPlayer.authenticated) 

            [[GKLocalPlayer localPlayer]
             authenticateWithCompletionHandler:^(NSError *error)
             
                 [self finishGameCenterAuthWithError:error];
             
             ];
        
    

知道我在这里做错了什么吗?

【问题讨论】:

【参考方案1】:

Ggrrrhhh 同样的问题,我想我找到了...ios6 已弃用 authenticateWithCompletionHandler 参见链接,建议您使用 AuthenticateHandler。

http://developer.apple.com/library/IOS/#documentation/GameKit/Reference/GKLocalPlayer_Ref/Reference/Reference.html#//apple_ref/occ/instp/GKLocalPlayer/authenticateHandler

这似乎有效...

GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
[localPlayer setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) 

//[localPlayer authenticateWithCompletionHandler:^(NSError *error)  OLD CODE!
    if (localPlayer.isAuthenticated)
    
        //do some stuff
    
    else 

        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"NOT AUTHORISED"
                                  message:@"YOUR'RE NOT LOGGED INTO GC."
                                  delegate:self
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil];
        [alertView show];

    
)];

【讨论】:

这确实是问题所在。我附近还有一些额外的 cmets 作为另一个答案。 是的,感谢 iOS 6 与其他版本的构建。我也相信 presentModalViewController 也在 ios 6 的名单上。【参考方案2】:

Jamie West 正确指出问题在于 iOS6 中的 authenticateHandler 转换,这似乎导致 authenticateWithCompletionHandler: 损坏。由于它已被弃用,Apple 不太可能修复他们的错误。

这里有我需要的一切。注意检查 iOS5 版本的条件(同时支持 5 和 6)以及在发送视图控制器时调用视图控制器的需要(例如,authenticateHandler: 不是 authenticateWithCompletionHandler: 的直接替代: - 你必须做一些额外的工作)。

-(void)authenticateLocalUser 

    if (!self.checkingLocalPlayer) 
        self.checkingLocalPlayer = YES;
        GKLocalPlayer *thisPlayer = [GKLocalPlayer localPlayer];

        if (!thisPlayer.authenticated) 

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v)  ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)

            if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) 

                [thisPlayer setAuthenticateHandler:(^(UIViewController* viewcontroller, NSError *error) 

                    if (viewcontroller) 
                        [self.delegate presentViewController:viewcontroller];
                     else 
                        [self finishGameCenterAuthWithError:error];
                    

                )];

             else 

                [[GKLocalPlayer localPlayer]
                 authenticateWithCompletionHandler:^(NSError *error)
                 
                     [self finishGameCenterAuthWithError:error];
                 
                 ];
            

        
    

presentViewController: 函数只是从我的顶视图控制器中调用新的视图控制器(我必须在我的程序中手动计算才能使所有这些工作):

-(void)presentViewController:(UIViewController *)thisVC 

    [myTopVC presentModalViewController:thisVC animated:YES];


不幸的是,从 iOS6 开始,如果 GameCenter 在当前会话中已被取消,似乎不会尝试重新验证用户,因此至少我在适当时重新验证的一些观点已经不复存在。但是,它仍然适用于 iOS5(可能还有其他情况,而不是取消?)。

会在应用程序从睡眠状态被调用时尝试重新验证,如果用户已经完成了其他操作。

【讨论】:

有什么理由要检查 iOS 版本而不是检查 setAuthenticateHandler: 方法是否可用?我想知道这是否可能只是在 iOS 中没有记录 好吧,除非绝对必要,Apple 强烈建议检查选择器和类的可用性,而不是检查特定的 iOS 版本。如果您想被提醒原因,您可以随时在代码中添加注释...【参考方案3】:

我遇到了完全相同的问题和类似的崩溃消息,上面的答案并没有解决问题。

2012-09-25 15:55:25.569 APP NAME [1493:907] * Terminating app due to uncaught exception
'NSInternalInconsistencyException', reason: 'Attempting to begin a modal transition from
<GKModalRootViewController: 0x1cd8b2a0> to <GKHostedAuthenticateViewController: 0x1e31a350>
 while a transition is already in progress. Wait for viewDidAppear/viewDidDisappear to know
the current transition has completed' 

实际上对我造成问题的是我从 -(void)viewDidLoad 调用了 -(void)authenticateLocalPlayer。一旦我将调用移至 -(void) viewDidAppear,它就修复了所有问题,即使是不推荐使用的调用方式。 (reference to this question)

- (void)viewDidAppear:(BOOL)animated

    [super viewDidAppear:animated];

    //Setup Game Center Manager
    if ([GameCenterManager isGameCenterAvailable])   
        delegate.gameCenterManager = [[GameCenterManager alloc] init];
        [delegate.gameCenterManager setDelegate:delegate];
        [delegate.gameCenterManager authenticateLocalUser];
     else 
        // The current device does not support Game Center.
    

    //... more things if you have

【讨论】:

按要求发布代码。

以上是关于iOS6 上的 GKLocalPlayer 身份验证崩溃并出现模态转换错误的主要内容,如果未能解决你的问题,请参考以下文章

奇怪的 GameKit 错误。 GKLocalPlayer 正在返回对手

GameKit 自动呈现身份验证视图控制器,而不是等待我呈现它

我用的是window server 2003系统, 管理工具 计算机管理中:无本地用户和组,如何调出?另用window 身份验...

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

iOS6 上的虚拟键盘错误(使用 FPC)

由于 iOS6 上的全局外观属性,MFMailComposeViewController 崩溃