2

I have used [[GKTurnBasedEventHandler sharedTurnBasedEventHandler] setDelegate:self]; but I am not receiving delegate calls. This was working at one point, and I can't figure out for the life of me what has changed.

The app is properly badged (on the device home screen, it shows a badge with the number of games where it is my turn). Furthermore, using GKTurnBasedMatch loadMatchesWithCompletionHandler: is able to detect when it is the player's turn (or not). In fact, in every other conceivable way, GameCenter seems to be working perfectly. I can even send (and accept) challenges, but again, the delegate methods are not called: none of the GKTurnBasedEventHandlerDelegate methods are invoked (including handleTurnEventForMatch:, handleInviteFromGameCenter:, etc.)

It gets even weirder: if I quit the app entirely and it becomes my turn, I don't see any GameCenter notification. However, I DO se a badge on my app! if I simply open the GameCenter app itself, I also see that it is my turn. So, even the OS-level notifications are not being received, despite the fact that the data is properly updated on the server...

I've heard talk that maybe the GameCenter Sandbox is just unreliable with notification delivery... but I really can't take that risk. I need to test my code!

Things I've tried:

  1. Ensured that I am testing on real devices (no simulators). I've tested on 4 real devices, including an iPhones+iPads and iOS6+iOS7.
  2. I am doing a NSAssert([GKTurnBasedEventHandler sharedTurnBasedEventHandler].delegate == self every 60 seconds to ensure that the delegate property is not lost (per this question: handleTurnEventForMatch:didBecomeActive: callbacks only arriving some of the time)
  3. Double checked that I have push notifications enabled for the app within Settings
  4. Checked that the iTunesConnect version is exactly equal to my CFBundleShortVersionString in info.plist (0.0.1) and that iTunesConnect shows GameCenter as "enabled" for the game. I even also set the CFBundleVersion to also be the same value, just to ensure that there was no chance of confusion.
  5. Playing with the version #s in step 3. I've set them each to be 1.0.0 and 1.0 and 0.1, etc. I also print them out with a NSLog to make sure that they are properly copied into the app.
  6. Checked that I'm using explicit provisioning profiles, downloaded from developer.apple.com, and that XCode shows checkmarks next to all of the GameCenter steps in Capabilities. (e.g., I am not using "teams"; I have logged into the provisioning profile center and created a Development profile, downloaded it, and explicitly set it to my Provisioning Profile in Build Settings for Debug mode).
  7. Explicitly requesting push notification permissions. I was able to successfully retrieve (and use) a token, so there seems to be no problem with the APN service.
  8. I've also tried simply... waiting. I have the debugger attached to the device whose turn it is becoming. 10+ minutes after the turn has been passed off, no delegate is hit (I'm using a breakpoint to determine this).

Update This question was interesting: Sandbox Game Center Turn Event Notifications Not Consistent It led me to attempt to use [[GKLocalPlayer localPlayer] registerListener:self] instead of the GKTurnBasedEventHandler delegate method. Unfortunately, the problem was still not fixed. I even tried compiling with the minimum version of the SDK set to 7.0 (since this is a 7+ feature addition).

Community
  • 1
  • 1
Zane Claes
  • 14,732
  • 15
  • 74
  • 131
  • Commenting only to confirm that this is happening to me also, on a previously working sandbox app. I did not come up with a better "fix" for testing than polling. – jnic Jan 04 '14 at 15:29
  • Same issue here and about ready to resort to polling as you have done! This seems to be very common - several Qs on SO and in apple dev forums. Re push notifications, I haven't got these in my profile but I notice that other apps (e.g. Letterpress) don't seem to either and work OK in production at least. Of course perhaps they have polling workarounds too. – frankodwyer Jan 05 '14 at 02:30
  • One further comment, I don't see game invites either. However, if you go into the game centre app you can accept an invite OR press the button play your turn from there. In this case, the delegate IS called (the only case where I've ever seen it called - but it's consistently called, with didBecomeActive YES). Also, I wonder if this is really a backend problem given the turns are arriving timely in game centre every time, and the app is getting badged - suggests the APNs for game centre are happening and some config issue somewhere is preventing them from going the last few yards to the app:-) – frankodwyer Jan 05 '14 at 02:32

2 Answers2

1

My current belief is that the GameCenter Sandbox is at fault, since it seems like many people have had problems with it. To be able to test my code, I actually wrote some code to poll GameCenter and look for changes.

WARNING This is DUMB. I have it enabled in DEBUG mode only, simply so that I can test my handleTurnEventForMatch code. That said... it works around the problem.

This code can go into the same class that provides your delegate methods. You'll need to do some obvious logic modifications. You should call onMultiplayerGameStarted and onEndedMultiplayerTurn in the appropriate places from your gameplay logic.

#if GAMEKIT_TURN_POLLING

NSMutableDictionary *_wasLocalPlayersTurnMap = nil;

- (void)pollGameCenter {
  if(!_wasLocalPlayersTurnMap) {
    _wasLocalPlayersTurnMap = [NSMutableDictionary new];
  }
  [AMGameData loadGames:^(NSArray *games) {
    NSInteger validGameCount = 0;
    for(AMGameData *gameData in games) {
      if(gameData.isSinglePlayer) {
        continue;
      }
      if(gameData.gameState != AMGameStatePlaying) {
        continue;
      }
      validGameCount++;
      if([_wasLocalPlayersTurnMap[gameData.name] boolValue]) {
        continue;
      }
      if(!gameData.isLocalPlayersTurn) {
        _wasLocalPlayersTurnMap[gameData.name] = @(NO);
        continue;
      }
      // Hey, it's now our turn!
      _wasLocalPlayersTurnMap[gameData.name] = @(YES);
      [self handleTurnEventForMatch:gameData.match didBecomeActive:NO];
    }
    if(validGameCount) {
      // Need to do this again later...
      [self delayedPollGameCenter];
    }
  }];
}

- (void)delayedPollGameCenter {
  [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(pollGameCenter) object:nil];
  [self performSelector:@selector(pollGameCenter) withObject:nil afterDelay:10];
}

- (void)onMultiplayerGameStarted {
  [self delayedPollGameCenter];
}

- (void)onEndedMultiplayerTurn:(AMGameData*)gameData {
  _wasLocalPlayersTurnMap[gameData.name] = @(NO);
  [self delayedPollGameCenter];
}

#else
- (void)onMultiplayerGameStarted{}
- (void)onEndedMultiplayerTurn:(AMGameData*)gameData {}
#endif
Zane Claes
  • 14,732
  • 15
  • 74
  • 131
1

I'm having the same problems as well. I'm getting notifications around ~ 25% of time and I can't test properly the app.

According to the documentation, GKTurnBasedEventHandler is deprecated on iOS7. If this is true - could this be the reason for these issues?

https://developer.apple.com/library/ios/documentation/GameKit/Reference/GKTurnBasedEventHandler_Ref/Reference/Reference.html

Noam Behar
  • 201
  • 2
  • 11
  • Is it true? Yes, the Apple documentation is "the source of truth." However, deprecated does not mean non-functional; in fact, if you want to support iOS6 you'll NEED to use these methods. I've also tested this on iOS6 devices without any better luck. – Zane Claes Feb 12 '14 at 18:30
  • Well, I guess this is true. I'm still having problems with getting events. I've opened a bug on it but there's no response from Apple - Pretty frustrating. If anyone has an update - please post here. – Noam Behar Feb 15 '14 at 18:28