iosgame-centergkgamesession

GKGameSession- saveData always fails with malloc error after getShareURLWithCompletionHandler


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?


Solution

  • 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.