I am using Game Center turn-based matches for my card game. It feels like a good fit because people want to check their email or write a text sometimes between turns. Some users have said that they do really want to be able to have a very asynchronous playing experience.
For the people that are keeping the game open between their turns, I want to update the screen to reflect things that the other players are doing on their turns. I have set up a listener on GKLocalPlayer
that responds to player:receivedTurnEventForMatch:didBecomeActive
. The documentation says that this will get called when match data is saved by another player even if it doesn't become the player's turn (the player on the current device). That doesn't appear to be true 100% of the time. In fact, it appears that it only gets called about 1 in 3 times that match data is saved by other players. It seems more reliable when it becomes the player's turn, but even that isn't 100% reliable.
I am using saveCurrentTurnWithMatchData:completionHandler:
on GKTurnBasedMatch
to save match data that doesn't end the current player's turn and I'm calling endTurnWithNextParticipants:turnTimeout:matchData:completionHandler:
on GKTurnBasedMatch
to save the data when it does end the current player's turn. There are a few scenarios where I want to call saveCurrentTurn…
with updated matchData. In my game, you can have computers playing in your multiplayer game as well. So, a human player may play a card and then a computer may play a card before that GKPlayer
's turn ends. There are also scenarios where an individual player may play twice. (eg. A player plays the last card on a trick. That player takes the trick and gets to lead the next trick.)
I have set up a ton of logging around this and I can see clear scenarios where one device calls saveCurrentTurn…
and the completionHandler is called without an error and the other device doesn't get notified with a call to player:receivedTurnEvent…
I have also added logging to verify that each time I'm calling saveCurrentTurn…
that I'm calling it with new matchData. I'm not making redundant calls.
If I go to the device that didn't get the updated matchData and force it to load the matchData for the match again, it gets the updated data. So, it's definitely getting saved.
I have tried throttling the calls to saveCurrentTurn…
so that they don't happen in immediate succession and that didn't help.
Both devices in my testing are running iOS 8.4. There appears to have been an issue in iOS 8.3 that is fixed now (see this question). This Apple forum post also reports this issue 2 years ago and it appears that bug reports were filed and marked fixed.
Has anyone else seen this? I would love to know that I'm doing something wrong. Any ideas are very welcome.