Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

endTurnWithNextParticipants doesn't trigger receivedTurnEventForMatch after update to iOS 8.3 and swift 1.2

Has anyone noticed any changes to turn based match notifications since updating to iOS8.3? In my app when I call endTurnWithNextParticipants, prior to the upgrade, this was resulting in a notification being sent to the opponent which would trigger a receivedTurnEventForMatch being invoked on their device but this no longer is the case. When the opponent terminates the app and restarts it they can see it is their turn so the match in game centre was correctly updated with the order of participation but this doesn't seem to take effect dynamically any more.

Anybody else see this? I'm hoping it's just a temporary glitch in game centre sandbox environment.

I have raised a bug report with apple to see if it actually is a bug or if there is some undocumented behavioural changes in iOS8.3 we need to know about.

like image 253
Pinxaton Avatar asked Apr 10 '15 19:04

Pinxaton


1 Answers

Updated answer:

My original idea, below, turns out to not be reliable. You cannot count on the saveCurrentTurnWithMatchData to send timely notifications. It works most of the time, but at least 10% of the time, it fails to send a notifications as well. Of all the ideas posted here, the only thing I have found that works 100% reliably is to set up a timer loop on the non-active machines and continuously watch until you become active.

-(void)isMatchActive:(NSTimer *)timer
{
    NSString *matchID = (NSString *)timer.userInfo;

    [GKTurnBasedMatch loadMatchWithID:matchID withCompletionHandler:^(GKTurnBasedMatch *match, NSError *error)
    {
        GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
        GKTurnBasedParticipant *currentParticipant = match.currentParticipant;

        if ([localPlayer.playerID isEqualToString:currentParticipant.player.playerID])
        {
            //we have become active. Call the event handler like it's supposed to be called
            [self player:localPlayer receivedTurnEventForMatch:match didBecomeActive:false];
        }
        else
        {
            //we are still waiting to become active. Check back soon
            float dTime = 5.0;
            gameController.IOS8BugTimer = [NSTimer scheduledTimerWithTimeInterval:dTime
                                                                          target:self
                                                                     selector:@selector(isMatchActive:)
                                                                     userInfo:matchID
                                                                      repeats:NO];
         }
     }];
}

Original Answer:

So, I have a work around that is kludgy but looks promising. Note that, per my comment above, the subsequent players still receive events after the current player executes saveCurrentTurnWithMatchData. So I use that send my own custom signal:

  1. I added a string to my matchData for the "next player's ID."

  2. Right before I call endTurnWithNextParticipants, I set that string to the ID of the next player in the rotation.

  3. I call saveCurrentTurnWithMatchData

  4. I moved the call to endTurnWithNextParticipants inside saveCurrentTurnWithMatchData's completion handler, to ensure it doesn't fire until after saveCurrentTurnWithMatchData.

  5. For the purposes of this work around, I added the GKTurnBasedEventHandlerDelegate to my code. handleTurnEventForMatch is broken in 8.3 too, but I consolidated all of my workaround code there and didn't have to make changes to receivedTurnEventForMatch

  6. In handleTurnEventForMatch, I check to see if the "next player" string is me. If so, I assume that the current player just saved the game in step 2, signalling his intention to pass the turn to me.

  7. I start a timer loop, reloading the match data until it shows that I have become the active player.

  8. When I see that I am now the active player, I reset my custom next player string to nil and I manually call receivedTurnEventForMatch passing it the match data I just downloaded.

To summarize, player1 sends an extra saveTurn event to signal that he intends to end the turn. When player2 receives that signal, he re-reads the match data until it shows that he has become active. Then he calls his own receivedTurnEventForMatch with the updated match data, allowing the turn to proceed.

I haven't gotten through all my scenarios yet, but it looks like this is going to work.

like image 196
Thunk Avatar answered Oct 19 '22 04:10

Thunk