还有其他人看到这个问题吗?我希望这只是游戏中心沙盒环境中的暂时性故障。
我已向苹果提出了一个错误报告,以查看它是否真的是一个错误,或者iOS8.3中是否有一些未记录的行为变化我们需要知道。
-(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];
}
}];
}
原始回答:
因此,我有一个解决方法,虽然有点笨拙但看起来很有前途。请注意,根据我上面的评论,当前玩家执行saveCurrentTurnWithMatchData后,后续玩家仍会接收事件。所以我使用它发送自己的自定义信号:
我为“下一个玩家ID”添加了一个字符串到我的matchData中。
在调用endTurnWithNextParticipants之前,我将该字符串设置为旋转中下一个玩家的ID。
我调用了saveCurrentTurnWithMatchData
我将对endTurnWithNextParticipants的调用移动到saveCurrentTurnWithMatchData的完成处理程序中,以确保它在saveCurrentTurnWithMatchData之后才触发。
出于此解决方法的目的,我将GKTurnBasedEventHandlerDelegate添加到了我的代码中。handleTurnEventForMatch在8.3中也已经失效,但我将所有的解决办法都合并到那里,并且不需要对receivedTurnEventForMatch进行更改。
在handleTurnEventForMatch中,我检查“下一个玩家”字符串是否为我。如果是,我认为当前玩家刚刚在步骤2中保存了游戏,表示他打算将轮到我。
我启动一个计时器循环,重新加载比赛数据,直到它显示我已成为活跃玩家。
当我看到我现在是活跃玩家时,我将我的自定义下一个玩家字符串重置为nil,并手动调用receivedTurnEventForMatch,并传递我刚刚下载的比赛数据。
总之,player1发送了额外的saveTurn事件来表示他打算结束回合。当player2收到该信号时,他会重新读取比赛数据,直到它显示他已经成为活跃玩家。然后他使用更新的比赛数据调用自己的receivedTurnEventForMatch,以允许回合继续进行。
我还没有处理完所有场景,但看起来这样做是可行的。
更新: 苹果已经回应了这个漏洞报告:
请在iOS 8.4 beta 4 (Build: 12H4125a)上验证此问题,并使用您的结果更新您的漏洞报告http://bugreport.apple.com/。
iOS 8.4 beta 4 (Build: 12H4125a) https://developer.apple.com/ios/download/ 发布日期: 2015年6月9日
不幸的是,我无法在我的设备上安装iOS 8.4 beta 4,也无法告诉你它是否已经修复。如果你们中有任何人有这个机会,请分享一下。
- (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");
}
}];
}
}];
}
}
我们在iOS 8.3下遇到了同样的问题,但在昨天发布的iOS 8.4版本中已经修复。
更新1
就我们的情况而言,@appsunited的解决方法确实解决了iOS 8.3的问题,并且在iOS 8.4中不再需要。
我们测试了沙盒和当前的应用商店版本。并且使用一台安装了iOS 7.1.2的iPad 3与另外一台安装了昨天的iOS 8.3和8.4的iPad 3进行了对比测试。