2013-03-12 9 views
15

Sto facendo qualche esperimento per cercare di conoscere GameKit e ho creato un gioco semplice e un'interfaccia che elenca le partite del mio giocatore. Sto cercando di aggiungere la possibilità di rimuovere i giochi utilizzando il metodo removeWithCompletionHandler: sulla partita, ma ho difficoltà a rimuovere uno GKTurnBasedMatch che sembra aver inserito uno stato non valido.Rimozione di un GKTurnBasedMatch che si trova in uno stato non valido

un pò di partita in questione stampe:

$0 = 0x1d590d20 <GKTurnBasedMatch 0x1d590d20 id:858d8257-cc49-4060-b1d8-38c09a929e3c status:Ended message: taken:2013-03-08 18:08:47 +0000 created:2013-03-08 03:24:14 +0000 
current:<GKTurnBasedParticipant 0x1d58c020 - id:G:1717956303 (local player) status:Invited outcome:None lastTurn:(null)> 
participants: 
    <GKTurnBasedParticipant 0x1d58bc90 - id:G:1717239488 status:Done outcome:Quit lastTurn:2013-03-08 18:08:47 +0000> 
    <GKTurnBasedParticipant 0x1d58c020 - id:G:1717956303 (local player) status:Invited outcome:None lastTurn:(null)> 
> 

che sembra indicare che la partita è stata terminata. Tuttavia, uno dei partecipanti ha il risultato: Nessuno, che sono guidato dai documenti a credere non valido per un gioco finito. Cercando di rimuovere semplicemente il gioco dà:

The requested operations could not be completed because one or more parameters are invalid.

Durante il tentativo di impostare i risultati e terminare il gioco dà:

The requested operation could not be completed because the session is in an invalid state.

ho pensato che forse non ho potuto rimuovere il gioco perché il giocatore locale è il principio attivo partecipante, ma entrambi participantQuitInTurnWithOutcome:... e endTurnWithNextParticipants:... entrambi danno l'errore:

The requested operation could not be completed because the session is in an invalid state.

pure. Sto facendo qualcosa di sbagliato o ho in qualche modo creato un gioco inamovibile?

P.S. Non riesco nemmeno a rimuovere i giochi tramite l'interfaccia fornita dal Game Center, dove sono elencati nella sezione "Game Over".

+0

La risposta di Henrik dovrebbe risolvere il tuo problema. Devi chiamare declineInviteWithCompletionHandler: –

risposta

5

Sfortunatamente, ho eseguito esattamente lo stesso errore. Per aiutare gli altri a capire il problema, nella speranza di cercare una soluzione, puoi ricreare questo invitando un amico a una partita, ma poi lasciare la partita durante il primo turno prima di inviare quel turno al giocatore invitato. Quindi, il giocatore ospitante rimuove la partita dal Game Center. Sul dispositivo del giocatore invitato, avranno una corrispondenza simile a quella di cui sopra, che non può essere cancellata. Ho provato tutti i tipi di soluzioni alternative.

Non ho ancora avuto fortuna, ma aggiornerò la mia risposta con una soluzione se la trovo. Attualmente sto cercando di spedire un gioco Game Center e quindi devo trovare un modo per aggirare questo. Avrò una conclusione entro il prossimo giorno o due.

AGGIORNAMENTO: Sono andato oltre le mie partite non eliminabili, e sono quasi uguali al tuo tranne il mio giocatore con lo stato Invitato ha anche il risultato della partita di Vinto. Sembra che la chiave per mettere la partita in uno stato non valido è avere uno stato di giocatore essere Invitato invece di Fatto, ma avere lo stato della partita essere Finito. Questo è l'elemento comune tra i nostri due casi ed è un caso limite nel codice bizantino di Game Center di Apple. Non mi sorprenderebbe se avessero semplicemente rovinato questo caso limite e ti aspettassi di "solo sapere" che non dovresti mettere i giocatori in quello stato (senza dubbio se leggi i loro documenti abbastanza da essere in grado di unire questo alla fine).

La mia conclusione è che Apple ha un caso limite sulle mani che passa inosservato facilmente perché può accadere solo se si esce da una nuova partita, e solo se si invita un amico, due casi potrebbero non essere testati spesso. Inoltre, se non stai impostando i risultati della corrispondenza in modo errato, suppongo che non accadrà mai così semplicemente non li hanno mai catturati.

Dal momento che non ho ancora inviato, ho intenzione di configurare la mia app per rilevare le partite in questo stato e ignorarle. Riferirò alla console un conteggio di quante partite ci sono in questo stato, solo così posso assicurarmi che non superi questo punto.Quindi, analizzerò il mio codice di chiusura e mi assicurerò che in questo caso limite non possa mai più mettere una partita in questo stato. Penso che, dato quello che sappiamo, dobbiamo essere proattivi, e semplicemente risucchiare il fatto che alcune partite siano sfuggite.

Speriamo che non sia ancora stato spedito, quindi le corrispondenze del caso di errore saranno localizzate nell'ambiente Sandbox di Game Center. In realtà, le cattive corrispondenze sono solo localizzate per l'utente di test nella Sandbox, quindi puoi semplicemente gettare via quell'utente e iniziare con un nuovo utente dopo aver corretto il problema. Se implementi i miei suggerimenti sopra riportati, dovresti essere in grado di confermare che la tua app funzioni correttamente prima di eseguire questo passaggio.

Se qualcuno può effettivamente trovare un modo per rimuovere le corrispondenze di errore una volta che esistono, faccelo sapere, ma spero che i miei suggerimenti e l'identificazione della causa effettiva saranno sufficienti per aiutarti a procedere con il tuo progetto.

+0

Sono stato in grado di rimuovere queste corrispondenze di errore impostando 'participant.matchOutcome = GKTurnBasedMatchOutcomeTied' per tutti i partecipanti e poi chiamando' [match removeWithCompletionHandler ...] '. Non è qualcosa che terrò nel mio codice, ma ha eliminato i giochi non validi. – Jon

4

Ho una situazione simile, se leggermente diversa. Comincio una partita, invito un secondo account sandbox a giocare, quindi il primo giocatore chiude e cancella il gioco prima che il secondo giocatore possa rispondere. Quando il secondo giocatore cerca di poi uscire dal gioco, ottengono questo errore:

Error quitting match in turn: Error Domain=GKErrorDomain Code=22 "The requested operation could not be completed because the specified participant is invalid." 
UserInfo=0x1f5de800 { 
    GKServerStatusCode=5097, 
    NSUnderlyingError=0x1f58b610 "The operation couldn’t be completed. 
    status = 5097, 
    Invalid state: turn sent to playerId:1952436619 in slotIndex: 0 for sessionId: 698b074b-fa0b-4505-834f-1b4305b7eecb : expected slot state: Active but found: Inactive", 
    NSLocalizedDescription=The requested operation could not be completed because the specified participant is invalid. 
} 

Quindi, per quanto mi riguarda posso dire, quello che sta succedendo perché la prossima partecipante a muoversi già ha uno stato di "Done", che ho sto indovinando perché hanno già smesso:

<GKTurnBasedMatch 0x1f532b20 id:698b074b-fa0b-4505-834f-1b4305b7eecb status:Open message: taken:2013-03-30 19:53:47 +0000 created:2013-03-30 18:29:09 +0000 
current:<GKTurnBasedParticipant 0x1f532b80 - id:G:1952433332 (local player) status:Active outcome:None lastTurn:2013-03-30 19:53:47 +0000> 
participants: 
     <GKTurnBasedParticipant 0x1f532b70 - id:G:1952436619 status:Done outcome:Lost lastTurn:2013-03-30 18:29:10 +0000> 
     <GKTurnBasedParticipant 0x1f532b80 - id:G:1952433332 (local player) status:Active outcome:None lastTurn:2013-03-30 19:53:47 +0000> 
    > 

Speriamo che questo possa aiutare gli altri a diagnosticare se non altro. Mi piacerebbe sentire le intuizioni degli altri verso una soluzione o una soluzione. Se questo è un bug da parte di Apple, sembra che valga la pena archiviare un radar.

2

Supporto tecnico dello sviluppatore Apple ha confermato il problema. Segnalazione bug inoltrata. Vi terrò aggiornati.

+0

Felice di sentire qualcuno che lo segue. Grazie, Valentyn. – Zach

+0

Eventuali aggiornamenti su questo? Puoi per favore pubblicare un link in cui il problema è tracciato. – Drux

7

In questo modo sono riuscito a rimuovere tutte le corrispondenze non valide.

Ho controllato lo stato del partecipante corrente, se è stato invitato, ho chiamato declineInviteWithCompletionHandler, altrimenti ho chiamato participantQuitInTurnWithOutcome.

In entrambi i blocchi di completamento, ho quindi chiamato removeWithCompletionHandler per rimuovere la corrispondenza.

Questo ha generato alcuni errori ma le corrispondenze sono state ancora rimosse quindi la mia lista è pulita.

Ed ecco una soluzione alternativa su come evitare di arrivare a questo stato per cominciare. Questo ha l'ulteriore vantaggio che l'invitato non riceve mai una notifica se l'inviter si interrompe prima di terminare il suo primo turno.

In playerQuitForMatch, prima terminare il turno e quindi nel gestore di completamento, chiudere immediatamente la partita. Mi piace così,

[match endTurnWithNextParticipants:[NSArray arrayWithObject:nextParticipant] 
              turnTimeout:GKTurnTimeoutDefault 
              matchData:nil completionHandler:^(NSError *error) { 
               if (error) { 
                NSLog(@"%@", error); 
               } 

               [match participantQuitOutOfTurnWithOutcome:GKTurnBasedMatchOutcomeQuit 
                    withCompletionHandler:^(NSError *error) { 
                     if (error) { 
                      NSLog(@"%@" ,error); 
                     } 
                    }]; 
              }]; 
+0

Grazie! Ha funzionato perfettamente per me! –

+0

Quello! Grazie mille muchas. – Binarian

5

Ho trovato la soluzione. Per le corrispondenze non valide utilizzare solo il metodo -participantQuitOutOfTurn e quindi il metodo -removeWithCompletionHandler. Sarà completamente rimosso.

Problemi correlati