更新到iOS 8.3和swift 1.2后,endTurnWithNextParticipants不会触发receivedTurnEventForMatch事件。

10
有没有人发现在更新到iOS8.3后,回合制比赛通知有什么改变?在我的应用中,当我调用endTurnWithNextParticipants之前,在升级之前,这会导致向对手发送通知,从而在对手的设备上触发receivedTurnEventForMatch的调用,但现在不再是这种情况了。当对手终止应用程序并重新启动它时,他们可以看到轮到他们了,因此游戏中心中的比赛已正确更新参与顺序,但这似乎不再动态生效。
还有其他人看到这个问题吗?我希望这只是游戏中心沙盒环境中的暂时性故障。
我已向苹果提出了一个错误报告,以查看它是否真的是一个错误,或者iOS8.3中是否有一些未记录的行为变化我们需要知道。

一样的问题。这是一个严重的错误,我们现在是否应该不断重新加载所有匹配项以检查新的匹配项?希望这很快能得到解决。如果有任何消息,请更新问题。 - J.Williams
2
我在这里也是一样的情况。完全破坏了我的游戏。为了防止这只是另一个“我也是”的帖子,我有一个额外的观察:如果你执行saveCurrentTurnWithMatchData:,其他玩家仍然会收到通知。 - Thunk
2
是的,我可以确认saveCurrentTurnWithMatchData会触发通知。 - Pinxaton
1
遇到了同样的问题。真高兴能找到这篇帖子。 - Hivebrain
同样的问题。我想添加,对我来说这并不一定是个问题。它只会在8.3设备上发生,但并非每个人都会出现这种情况。 - bdev
显示剩余3条评论
4个回答

4
更新的答案: 我的原始想法(如下)不可靠。你不能指望saveCurrentTurnWithMatchData及时发送通知。它大多数情况下能工作,但至少有10%的时间,它也无法发送通知。在这里发布的所有想法中,唯一我发现可以100%可靠地工作的是在非活动机器上设置一个定时器循环,并不断观察,直到你变成活动状态。
-(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后,后续玩家仍会接收事件。所以我使用它发送自己的自定义信号:

  1. 我为“下一个玩家ID”添加了一个字符串到我的matchData中。

  2. 在调用endTurnWithNextParticipants之前,我将该字符串设置为旋转中下一个玩家的ID。

  3. 我调用了saveCurrentTurnWithMatchData

  4. 我将对endTurnWithNextParticipants的调用移动到saveCurrentTurnWithMatchData的完成处理程序中,以确保它在saveCurrentTurnWithMatchData之后才触发。

  5. 出于此解决方法的目的,我将GKTurnBasedEventHandlerDelegate添加到了我的代码中。handleTurnEventForMatch在8.3中也已经失效,但我将所有的解决办法都合并到那里,并且不需要对receivedTurnEventForMatch进行更改。

  6. handleTurnEventForMatch中,我检查“下一个玩家”字符串是否为我。如果是,我认为当前玩家刚刚在步骤2中保存了游戏,表示他打算将轮到我。

  7. 我启动一个计时器循环,重新加载比赛数据,直到它显示我已成为活跃玩家。

  8. 当我看到我现在是活跃玩家时,我将我的自定义下一个玩家字符串重置为nil,并手动调用receivedTurnEventForMatch,并传递我刚刚下载的比赛数据。

总之,player1发送了额外的saveTurn事件来表示他打算结束回合。当player2收到该信号时,他会重新读取比赛数据,直到它显示他已经成为活跃玩家。然后他使用更新的比赛数据调用自己的receivedTurnEventForMatch,以允许回合继续进行。

我还没有处理完所有场景,但看起来这样做是可行的。


3

更新: 苹果已经回应了这个漏洞报告:

请在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");
                    }
                }];
            }
        }];
    }
}

@Appsunited:我认为你依赖这两个操作立即触发,以便在接收器获得(仍在工作的)saveCurrentTurn事件时,由于endTurn,它们已经是活动参与者,对吗?在我的测试中,我遇到了游戏中心端之间延迟的问题,因此当接收方收到第一个事件时,它不是当前参与者。(因此,我在接收器上启动了计时器循环以等待endTurn)。你的时间安排可靠吗? - Thunk
我看到与@Thunk报告的相同情况,使用此方法:已调用receivedTurnEvenForMatch,但currentParticipant仍然是刚刚结束回合的参与者。 - Trey Bean
我也确认,我的解决方案代码并没有像我希望的那样工作。这里有另一个解决方法:本地玩家有一个开放的比赛,并且正在等待对手结束回合,游戏每1-3秒钟加载一次该比赛并更新比赛数据,如果对手已经回应并加载了新的比赛数据。这也是一个hack和老派技巧,但到目前为止它可靠地工作着。 - appsunited
iOS 8.4现已发布。我已经测试过了,它又可以正常工作了。你不再需要任何解决方法了。 :-) - appsunited

3
我有同样的问题。我有多个设备,而8.3版本的设备没有触发receivedTurnEventForMatch事件,但是当应用程序在后台时,轮到你的通知横幅将像往常一样出现。问题只出现在应用程序在前台的情况下。
另一方面,运行8.2或8.1.3版本的设备在任何情况下都能正常工作。因此,这肯定是由8.3版本引起的。同时,8.3版本的设备在Xcode中被标记为不合格。你有遇到过类似的问题吗?

是的,这种情况也发生在我身上。我必须通过“产品”->“目标”-><设备>手动选择设备。 - Pinxaton
顺便说一下:我已经在iOS 8.3、8.0和7.1.2上进行了测试。只有7.1.2能够正确工作。 - appsunited

2

我们在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进行了对比测试。


好的,知道了。谢谢!至少这证实了苹果承认他们破坏了它。 - Pinxaton
1
Pinxaton,很抱歉听到这个消息。8.4版本现在对我来说已经正常工作了。 - Thunk
可能是我做错了什么。我会调查一下。 - Pinxaton
我仍然有这个问题。AppsUnited的各种解决方案似乎都有些作用,但并不好。游戏玩法会轮流进行一段时间,然后就卡住了。应该收到-receivedTurnEventForMatch通知的玩家没有收到通知,尽管Game Center显示轮到他了。在Game Center中进行回合操作可以正确地恢复游戏。我正在使用iPadMini和iPadAir2,两者均运行8.4。 - Paul Linsay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接