6

私のアプリは、Game Center で正常に認証されたかどうかの記録を保持しています。新しいゲームを開始するとき、またはユーザーがスコア リストを見たときに、ローカル プレーヤーが正常に認証されていない場合、およびその時点でアプリがユーザーの認証を試みている最中でない場合は、再試行します。 .

(理由は? 非ネットワーク ゾーンからネットワーク ゾーンに移動した場合)。

残念ながら、iOS6/XCode 4.5 では、クラッシュし始めました。または、少なくとも特定の限られた状況ではそうであるように思われます: ユーザーが間違ったパスワードや存在しないアカウントでログインに失敗した場合。ログインに成功すると、すべてがうまくいきます。

ログインに失敗した後、再認証チェックを発生させるようなことをすると、次のようになります。

2012-09-25 15:54:47.829 アプリ名 [1493:907] * -[UIWindowController transition:fromViewController:toViewController:target:didEndSelector:]、/SourceCache/UIKit/UIKit-2372/UIWindowController.m:211 でのアサーションの失敗

次に、これは実際にクラッシュします:

2012-09-25 15:55:25.569 アプリ名 [1493:907] * キャッチされていない例外 'NSInternalInconsistencyException' が原因でアプリを終了しています。移行はすでに進行中です。Wait for viewDidAppear/viewDidDisappear to know the current transition has completed' * First throw call stack: (0x394932a3 0x31db297f 0x3949315d 0x383fd2af 0x3640377b 0x36402fcf 0x394969c4 0x393edfeb 0x36521733 0x32a83d2d 0x3264b11f 0x3264a4b7 0x3264f1bd 0x39466f3b 0x393d9ebd 0x393d9d49 0x353132eb 0x3636b301 0x7e863 0x7e808) libc++abi.dylib: terminate called例外を投げる

これは厄介なコードです:

-(void)authenticateLocalUser {

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

        if (!thisPlayer.authenticated) {

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

ここで何が間違っているのか分かりますか?

4

3 に答える 3

7

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

    }
})];
于 2012-09-26T09:23:17.217 に答える
3

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 にはまだあります (キャンセル以外の状況でしょうか?)。

ユーザーが何か他のことを行った場合、アプリがスリープから復帰したときに再認証を試みます。

于 2012-09-26T19:31:31.703 に答える
1

まったく同じ問題と同様のクラッシュ メッセージがあり、上記の回答では問題が解決しませんでした。

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 への呼び出しを移動すると、非推奨の呼び出し方法であっても、すべてが修正されました。(この質問への参照

- (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
}
于 2013-02-26T00:50:42.440 に答える