2016-10-28 6 views
1

Я пытаюсь включить GKGameSession в игру в Game Center. Я пробовал несколько комбинаций из следующего кода: выполнял команды асинхронно, связывая их в обработчиках завершения и т. Д. Каждый раз, когда я вижу тот же результат, я могу использовать saveData просто отлично до Я звонил getShareURLWithCompletionHandler. После этого любая попытка saveData выдает сообщение об ошибке.GKGameSession- saveData всегда терпит неудачу с ошибкой malloc после getShareURLWithCompletionHandler

Вот простейший вариант кода, который демонстрирует проблему:

CKContainer *defaultContainer = [CKContainer defaultContainer]; 
[GKGameSession createSessionInContainer:defaultContainer.containerIdentifier 
           withTitle:@"temp title" 
        maxConnectedPlayers:4 
         completionHandler:^(GKGameSession * _Nullable session, NSError * _Nullable error) 
{ 
    if (error) 
    { 
     [self printError:error]; 
    } 

    [session getShareURLWithCompletionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) 
    { 
     if (error) 
     { 
      [self printError:error]; 
     } 
    }]; 


    NSData *newData = [NSData dataWithBytesNoCopy:@"abcdefghijklmnopqrstuvwxyz" length:26]; 
    [reSession saveData:newData completionHandler:^(NSData * _Nullable conflictingData, NSError * _Nullable error) 
    { 
      if (error) 
      { 
       [self printError:error]; 
      } 
    }]; 


}]; 

В большинстве случаев saveData вызов просто сбой:

malloc: *** error for object 0x32df14: pointer being freed was not allocated 
*** set a breakpoint in malloc_error_break to debug 

Но иногда выдает ошибку:

GKGameSessionErrorDomain:GKGameSessionErrorUnknown 

Я пробовал сохранять различные типы данных. Я попытался сделать последовательные вызовы, объединив все вызовы в обработчиках завершения. Я попытался сделать выборку URL и сохранить данные внутри и вне обработчика завершения creationSession.

Есть ли что-то, что я делаю неправильно здесь?

ответ

1

я вижу то же самое, но с более полезной ошибкой:

The requested operation could not be completed because the session has been updated on the server, causing a conflict.

Документация save говорит,

It is up to the developer to decide how to handle save conflicts.

Здесь, хотя, повторная попытка спасбросок терпит неудачу каждый раз, навсегда. Так что да, это то же самое состояние вы в.

Однако, когда игрок вступления в игру вводит URL на устройстве, называется их GKGameSessionEventListener «ы didAddPlayer:, а затем, если они спасают ... они получают одна и та же ошибка конфликта, но если они затем повторить сохранение ... это работает!

Игрок, создающий ссылку, заблокирован из сохранения или обновления состояния игры, пока игроки не обновили данные. Когда другой игрок сохраняет, исходный игрок получает звонок до session:player:didSave: на GKGameSessionEventListener.

В этот момент исходный игрок может сохранить как ожидалось.

+0

Очень интересная находка!Я открыл ошибку с Apple еще в октябре, а через несколько недель и без значимого ответа я вырвал весь код GK * и произвел свое собственное решение. Это на самом деле повторно применяет другую ошибку, которую я открыл: для приглашенного нет приглашения отклонить приглашение. Apple закрыла эту ошибку «по дизайну», заявив, что «игнорирование приглашения уменьшается». Но ваше обнаружение показывает, что создатель застрял в неиграбельной игре, если приглашенный никогда не признает приглашение и сохраняет данные. – Thunk

+1

Прохладный! Я бы хотел, чтобы у Apple был египтянин, играющий в SDK, или если он это сделал, более публичный. Можете ли вы поделиться дополнительной информацией о своем собственном решении? Например, что вы использовали на стороне сервера? –

+1

Я воспроизвел почти все функции GKturnbasedmatch и GKgamesession, используя только собственный CloudKit от Apple. Посмотрев видео wwdc на CloudKit, я убежден, что эти элементы GK * построены поверх него. Имея собственный контроль над схемой записи, я более точно контролирую уведомления. Поиск игроков, автоматизация, управление поворотами, облачное хранилище, все достигнутое с помощью CloudKit. Я еще не пробовал использовать CKShare для общих URL-адресов, но, похоже, это одно и то же. Поскольку комментарии настолько ограничены, если вы хотите получить больше информации, можете открыть новый вопрос, и я могу ответить подробно. – Thunk

0

Вы должны поставить один блок внутри другого. Поскольку блоки могут быть выполнены в любом порядке.

Я работаю код так:

NSData *newData = [NSData dataWithBytesNoCopy:@"abcdefghijklmnopqrstuvwxyz" length:26]; 
[reSession saveData:newData completionHandler:^(NSData * _Nullable conflictingData, NSError * _Nullable error) 
{ 
     if (error) 
     { 
      [self printError:error]; 
     } else { 
[session getShareURLWithCompletionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) 
{ 
    if (error) 
    { 
     [self printError:error]; 
    } 
}]; 

} }];

+0

спасибо, но это не блок-исполнение. Это первоначально появилось, когда сохранение произошло через 10-15 минут после получения URL-адреса. Дело в том, что независимо от того, являются ли блоки вложенными или нет или сколько времени прошло, каждая попытка сэкономить вызывает ошибку, если она возникает в любое время после получения URL-адреса. Мне было бы интересно узнать, что произойдет в вашем коде, если вы замените вызовы save и getShare (вставьте сохранение в блок завершения getShare) – Thunk

Смежные вопросы