Endturnwithnextparticipants Doesn't Trigger Receivedturneventformatch After Update to iOS 8.3 and Swift 1.2

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

Update:
Apple has responded to the bug report:

Please verify this issue with iOS 8.4 beta 4 (Build: 12H4125a) and
update your bug report at http://bugreport.apple.com/ with your
results.

iOS 8.4 beta 4 (Build: 12H4125a)
https://developer.apple.com/ios/download/ Posted: June 9th, 2015

Unfortunately I am not able to install iOS 8.4 beta 4 on my devices and can't tell you whether it's fixed now. If anybody of you has this opportunity, please share.


I have submitted a bug report to Apple regarding this issue and will post updates here when they have responded.

My turn-based game has this workaround. Looks terrible, but it's working again – maybe it helps you.

- (void)sendGameStateWith:(NSMutableDictionary *)data
{
if (self.match) {
NSData *matchdata = [NSKeyedArchiver archivedDataWithRootObject:data];

GKTurnBasedParticipant *opponent = [self.match.participants objectAtIndex:0];
GKTurnBasedParticipant *localPlayer = [self.match.participants objectAtIndex:1];
if ([self.localPlayer.playerID isEqualToString:opponent.playerID]) {
opponent = [self.match.participants objectAtIndex:1];
localPlayer = [self.match.participants objectAtIndex:0];
}

// HINT: Remove this workaround when Apple has fixed it.
[self.match saveCurrentTurnWithMatchData:matchdata completionHandler:^(NSError *error) {
if (error) {
NSLog(@"Error on saveCurrentTurnWithMatchData");
[self sendGameStateWith:data];

} else {
[self.match endTurnWithNextParticipants:[NSArray arrayWithObjects:opponent, localPlayer, nil] turnTimeout:turnTimeout matchData:matchdata completionHandler:^(NSError *error) {
if (error) {
NSLog(@"Error: Send Game Center state");
} else {
NSLog(@"Sent Game Center state");
}
}];
}
}];
}
}

GameCenter No Events Called

Are you testing on IOS8.3? If so, that event is broken in 8.3; the even handler never fires for the recipient. The bug is fixed in 8.4.

See endTurnWithNextParticipants doesn't trigger receivedTurnEventForMatch after update to iOS 8.3 and swift 1.2 for more details.

GameKit Turn-based listener is not reliably called when matchData changes

I do something similar. In my game, each player has multiple pieces, saving the match when each piece moves so that other players--if they're in the game--can watch what's happening in real time. Like you describe, the Game Center messaging is almost completely useless.

As you referenced, in 8.3, the "end of turn" messages were completely broken. As of 8.4, they happen most, but not all, of the time. As you're seeing, the "match has been saved" notifications are also erratic. Here are some tips I've used to increase the success rate:

  1. Slow down the saves. If you save too fast, only the last one arrives at the recipient. I set up an NSArray queue, and each time I want to save the match, I add the new matchData to that queue. I have a timer loop running that does the actual saveCurrentTurnWithMatchData, pops the item off the stack if the save was successful, and then sets up a new timer to call itself again a little later. I'm using 2 second intervals which seems to be working well.

  2. Append each new piece of data, don't overwrite. Put a sequence number on each piece of data. So, if you save seq numbers 1, 2, 3 and 4, but the recipient only receives a notice for #4, the records for 1, 2 and 3 are there in the match object. The recipient needs to track the last record it read, and then iterate through any new records from that point when it receives an updated matchData.

  3. I also use the queue's NSArray writeToFile: function to maintain a list of the pending saves. If the user exits the game before the queue is flushed, I reload the queue NSArray from disk at the next startup

  4. Note that even with this mechanism, the notifications to the recipient are erratic. Generally speaking, they arrive in batches of 4+. Then nothing happens until 3 or 4 more saves happen, which again all show up together. Making 1 save and letting the game sit for 10 minutes will probably never generate a notice on the recipient's machine. But, if you save 4 or 6 times in a row, all of them tend to show up in a burst.

  5. Sometimes, the notifications just stop for a few hours. Not sure if this a sandbox flaw or a game-center-in-general flaw. There are no failures of any kind, the messages just stop working for a while. Sometimes, the next morning, they show up in a burst. Sometimes not. In the end, I've stopped relying on the notifications. I set up another timer loop to continuously download the match. It checks if it has become my turn or not, it checks if new updates have been added to the matchData. Then calls player:receivedTurnEventForMatch:didBecomeActive. As far a receivedTurnEventForMatch: knows, it was launched because of an event and it merrily goes on about its business.

  6. It does seem that saving the match is pretty prompt. If you don't get an error, it seems pretty certain that the updated match is immediately available for other players to consume... they just need to know to consume it. The messaging framework, though, has to be viewed as completely unreliable and non-guaranteed. Hence, the timer loop to continuously poll the match.

Edit: arguably, once I implemented #2, #1 shouldn't really matter. Any notification received by the recipient will trigger reading all new records in the data. But, this "hardening" has evolved over the past few months as I wrestle with Game Center's shortcomings. I just haven't gotten around to removing #1.

Find all Database Objects by Name?

Assuming you have the right permissions:

SELECT *
FROM yourdatabasename.sys.all_objects
WHERE upper(name) like upper('my prefix%') --use UPPER for case-INsensitivity


Related Topics



Leave a reply



Submit