I'm trying to incorporate GKGameSession
into my Game Center game. I've tried several combinations of the following code: running the commands asynchronously, chaining them in the completion handlers, etc. Every time I see the same result: I can use saveData
just fine until I've called getShareURLWithCompletionHandler
. After that, any attempt to saveData
throws an error.
Here's the simplest version of code that exhibits the problem:
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];
}
}];
}];
In most cases, the saveData
call simply crashes:
malloc: *** error for object 0x32df14: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
But sometimes it throws an error:
GKGameSessionErrorDomain:GKGameSessionErrorUnknown
I've tried different kinds of data being saved. I've tried making the calls sequential by chaining all the calls in completion handlers. I've tried doing the URL fetch and data save inside and outside of the creationSession completion handler.
Is there something I'm doing wrong here?
I see the same, but with a more useful error:
The requested operation could not be completed because the session has been updated on the server, causing a conflict.
The save
documentation says,
It is up to the developer to decide how to handle save conflicts.
Here though, retrying the save fails every time, forever. So yeah, that's the same state you're in.
However, when the player joining the game enters the URL on their device, their GKGameSessionEventListener
's didAddPlayer:
is called, and then if they save... they get the same conflict error, but if they then retry the save... it works!
The player creating the link is locked out of saving or updating game state, until joining players have updated the data. When the other player saves, the original player gets a call to session:player:didSave:
on the GKGameSessionEventListener
.
At that point the original player can then save as expected.