Monday, October 14, 2013

GKSession didChangeState delegate not working in iOS 7

So the GKSession transfer code that has been working ever since iOS 4.0 decided to STOP working (1/2 way) under iOS 7. Yeah, right? what else is new? :-p

The specific error or problem was that the connect code to display the alert where the user drags a slider for the desired number of vouchers to transfer, was not showing on iOS 7 device.

The iOS 7 devices DID receive vouchers so that meant the GKSession WAS valid.

So, in debugging it I found that even though the delegate was set, the didConnectPeer callback was firing but the didChangeState: WAS NOT.

So.... an easy-peasy kludge of a patch now allows iOS 7 devices to transfer vouchers to their iOS 6 (and iOS 5) brethren.

- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)thePeerID toSession:(GKSession *)theSession 
{    
self.session = theSession;
self.session.delegate = self
    self.peerID = thePeerID; 
    
    [self.session setDataReceiveHandler:self withContext:NULL];
    [picker dismiss];
    picker.delegate = nil;
    
    float sysVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
    if (sysVersion > 6.9) {
       if (!didConnect)
           [self session:self.session peer:self.peerID didChangeState:GKPeerStateConnected];
    }
}

 Full disclosure: I also added a boolean flag so that the GKPeerStateConnected "state" will only fire once, regardless of "where" it came from.

        case GKPeerStateConnected:
            if (!didConnect) {
                didConnect = TRUE;
                NSLog(@"Peer %@ Connected", self.peerID);
                [self performSelector:@selector(promptForQty) withObject:self afterDelay:1.0];
                self.statusLabel.text = @"Connected";
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateNormal];
                [self.launchShareButton setTitle:@"Stop" forState:UIControlStateHighlighted];
                [self.connectingActivityIndicatorView stopAnimating];
            }
            break;

2 comments:

  1. Thanks for posting this. Unfortunately, I do not use the GKPeerPickerController interface as I've written my own. Hopefully there is another way to trigger the didChangeState delegate callback, but I haven't found it yet.

    Also, you might consider using NSNumberSearch for comparing iOS versions instead of a float that only gives you one decimal place while iOS is usually split between 3 separate version number segments.

    I use something like this to tell if the app is running on iOS 7 or later...

    if( [[[UIDevice currentDevice] systemVersion] compare:@"7.0" options:NSNumericSearch] > NSOrderedAscending )
    {
    // running iOS 7 or newer
    }

    ReplyDelete
  2. Thanks Richard,

    Hope you can resolve your issue.

    ReplyDelete