iosobjective-cuiviewcontrollergamekitgkmatchmaker

How to dismiss GKMatchmakerViewController if already being presented and present new instance when receiving invitation?


The following delegate method is called by gameKit, when a person accepts an invitation

-(void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
{
    NSLog(@"%@ accepted invite",player.playerID);

    RIYGameNavigationController *root = (RIYGameNavigationController*)[[[UIApplication sharedApplication]delegate]window].rootViewController;
    [root popToRootViewControllerAnimated:YES];
    GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc]initWithInvite:invite];
    mmvc.matchmakerDelegate = root.viewControllers[0];
    [[[[[UIApplication sharedApplication]delegate]window]rootViewController]presentViewController:mmvc animated:YES completion:nil];
}

This "works" when the user is not already presenting a GKMatchmakerViewController.

This does not work if the user is already using the GKMatchmakerViewController when the invite comes in (Eg: When the user is already trying to find a match). If this is the case, when the invite comes in, I get the following warning, and the controller with the invite is not presented (since there is already a matchmakercontroller being presented). As a result, the user cannot respond to an invite. (Nothing happens).

Warning: Attempt to present <GKMatchmakerViewController: 0x1458a250>  on <RIYGameNavigationController: 0x1461f190> which is already presenting <GKMatchmakerViewController: 0x1465fcb0>

In iOS6, one could get around this by doing:

 if([topLevelViewController modalViewController] != nil)      
[topLevelViewController dismissModalViewControllerAnimated:NO];

and then creating the GKMatchmakerViewController. dismissModalViewControllerAnimated: has been deprecated in iOS6. It is suggested to use dissmissViewControllerAnimated:completion: instead, but it doesn't work for me. This is what I tried:

-(void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
{
    NSLog(@"%@ accepted invite",player.playerID);

    RIYGameNavigationController *root = (RIYGameNavigationController*)[[[UIApplication sharedApplication]delegate]window].rootViewController;
    [root popToRootViewControllerAnimated:YES];
    if ([[root presentedViewController]class] == [GKMatchmakerViewController class]) {
        [root dismissViewControllerAnimated:YES completion:nil];
    }

    GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc]initWithInvite:invite];
    mmvc.matchmakerDelegate = root.viewControllers[0];
    [[[[[UIApplication sharedApplication]delegate]window]rootViewController]presentViewController:mmvc animated:YES completion:nil];
}

The if block gets entered, but the existing GKMatchmakerViewController is not dismissed, and the new one does not show up. If I put a break point in the if statement, when I "continue" after the break, the view controller is dismissed, but the new one does not pop up.

How can I get this working?


Solution

  • I got around this by presenting the view in the completion block.

    - (void)presentMatchmakerViewControllerWithInvite:(GKInvite *)invite
    {
        RIYGameNavigationController *root = (RIYGameNavigationController*)[[[UIApplication sharedApplication]delegate]window].rootViewController;
        GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc]initWithInvite:invite];
        mmvc.matchmakerDelegate = root.viewControllers[0];
        [[[[[UIApplication sharedApplication]delegate]window]rootViewController]presentViewController:mmvc animated:YES completion:nil];
    }
    
    -(void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
    {
         NSLog(@"%@ accepted invite",player.playerID);
         RIYGameNavigationController *root = (RIYGameNavigationController*)[[[UIApplication sharedApplication]delegate]window].rootViewController;
        [root popToRootViewControllerAnimated:YES];
        if ([[root presentedViewController]class] == [GKMatchmakerViewController class]) {
            [root dismissViewControllerAnimated:YES completion:^{
                [self presentMatchmakerViewControllerWithInvite:invite];
            }];
        }
        else
        {
            [self presentMatchmakerViewControllerWithInvite:invite];
        }
    }
    

    It seems to work, but I feel it is clumsy. If someone has a better answer I will mark that as the correct one