endTurnWithNextParticipants не запускает receiveTurnEventForMatch после обновления до iOS 8.3 и swift 1.2

Кто-нибудь заметил какие-либо изменения в пошаговых уведомлениях о матчах после обновления до iOS8.3? В моем приложении, когда я вызываю endTurnWithNextParticipants, перед обновлением это приводило к тому, что оппоненту отправлялось уведомление, которое инициировало бы вызывание receiveTurnEventForMatch на их устройстве, но это больше не так. Когда оппонент завершает приложение и перезапускает его, он видит, что это его очередь, поэтому матч в игровом центре был корректно обновлен в соответствии с порядком участия, но, похоже, это уже не действует динамически.

Кто-нибудь еще видел это? Я надеюсь, что это просто временная ошибка в среде песочницы игрового центра.

Я подготовил отчет об ошибке в Apple, чтобы узнать, действительно ли это ошибка или есть какие-то недокументированные поведенческие изменения в iOS8.3, о которых нам нужно знать.

4 ответа

Решение

Обновление: Apple ответила на сообщение об ошибке:

Пожалуйста, проверьте эту проблему с iOS 8.4 beta 4 (Build: 12H4125a) и обновите ваш отчет об ошибке на http://bugreport.apple.com/ с вашими результатами.

iOS 8.4 beta 4 (сборка: 12H4125a) https://developer.apple.com/ios/download/ Опубликовано: 9 июня 2015 г.

К сожалению, я не могу установить iOS 8.4 beta 4 на свои устройства и не могу сказать, исправлена ​​ли она сейчас. Если у кого-то из вас есть такая возможность, пожалуйста, поделитесь.


Я отправил в Apple отчет об ошибке по этой проблеме и опубликую обновления здесь, когда они ответят.

В моей пошаговой игре есть обходной путь. Выглядит ужасно, но снова работает - может быть, это поможет вам.

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

Обновленный ответ:

Моя оригинальная идея, ниже, оказывается не надежной. Вы не можете рассчитывать на 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. Я добавил строку в мои matchData для "ID следующего игрока".

  2. Прямо перед вызовом endTurnWithNextParticipants я установил в этой строке идентификатор следующего игрока в ротации.

  3. Я вызываю saveCurrentTurnWithMatchData

  4. Я переместил вызов endTurnWithNextParticipants внутри обработчика завершения saveCurrentTurnWithMatchData, чтобы убедиться, что он не сработает до тех пор, пока не будет сохранено до saveCurrentTurnWithMatchData.

  5. Для этой цели я добавил GKTurnBasedEventHandlerDelegate в свой код. handleTurnEventForMatch также не работает в 8.3, но я объединил там весь мой обходной код и не должен был вносить изменения в receiveTurnEventForMatch

  6. В handleTurnEventForMatch я проверяю, является ли строка "следующий игрок" мной. Если это так, я предполагаю, что текущий игрок только что сохранил игру на шаге 2, сигнализируя о своем намерении передать ход мне.

  7. Я запускаю цикл таймера, перезагружая данные матчей, пока они не покажут, что я стал активным игроком.

  8. Когда я вижу, что теперь я являюсь активным игроком, я сбрасываю свою пользовательскую строку следующего игрока на ноль, и я вручную вызываю receiveTurnEventForMatch, передавая ей данные о совпадениях, которые я только что загрузил.

Подводя итог, игрок1 отправляет дополнительное событие saveTurn, чтобы сообщить, что он намерен завершить ход. Когда игрок2 получает этот сигнал, он перечитывает данные матча, пока не покажет, что он стал активным. Затем он вызывает свой собственный receiveTurnEventForMatch с обновленными данными совпадений, позволяя продолжить ход.

Я еще не прошел все мои сценарии, но похоже, что это сработает.

У меня та же проблема.. У меня есть несколько устройств, и устройство с 8.3 не вызывает событие receiveTurnEventForMatch, но когда приложение находится в фоновом режиме, уведомление о повороте баннера будет появляться как обычно. Проблема только в том случае, когда приложение находится на переднем плане.

С другой стороны, устройства с 8.2 или 8.1.3 работают хорошо в любом случае. Так что это, безусловно, вызвано 8.3. Также устройство с 8.3 в Xcode помечено как неподходящее. С тобой тоже такое случается?

У нас была та же проблема под iOS 8.3, и она была исправлена ​​в вчерашнем выпуске iOS 8.4.

ОБНОВЛЕНИЕ 1

в нашем случае обходной путь @appsunited решил эту проблему для iOS 8.3 и больше не нужен для iOS 8.4.

мы протестировали как песочницу, так и нашу текущую версию магазина приложений. и играл с iPad 3 с iOS 7.1.2 против другого iPad 3 с iOS 8.3 и вчера 8.4.

Другие вопросы по тегам