Как поделиться сохраненными играми на разных устройствах?

Я внедрил GameKit в свою игру для iOS, включая функцию сохраненной игры.

Вот пример того, как я сохраняю и загружаю игру:

MobSvcSavedGameData.h

#ifndef MOBSVC_SAVEDGAMEDATA_H
#define MOBSVC_SAVEDGAMEDATA_H

#import <Foundation/Foundation.h>

@interface MobSvcSavedGameData : NSObject <NSCoding>

@property (readwrite, retain) NSString *data;

+(instancetype)sharedGameData;
-(void)reset;

@end


#endif /* MOBSVC_SAVEDGAMEDATA_H */

MobSvcSavedGameData.m

#import "MobSvcSavedGameData.h"
#import <Foundation/Foundation.h>

@interface MobSvcSavedGameData () <NSObject, NSCoding>

@end

@implementation MobSvcSavedGameData

#pragma mark MobSvcSavedGameData implementation

static NSString * const sgDataKey = @"data";

+ (instancetype)sharedGameData {
    static id sharedInstance = nil;

    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] init];
    });

    return sharedInstance;
}

- (void)reset
{
    self.data = nil;
}

- (void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.data forKey: sgDataKey];
}

- (nullable instancetype)initWithCoder:(nonnull NSCoder *)decoder {
    self = [self init];
    if (self) {
        self.data = [decoder decodeObjectForKey:sgDataKey];
    }
    return self;
}

@end

Для простоты мой сохраненный игровой объект выше имеет только NSString, который будет сериализован и загружен следующим образом:

void MobSvc::uploadSavedGameDataAwait(const char *name, const char *data)
{
    GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer];

    if(mobSvcAccount.isAuthenticated)
    {
        MobSvcSavedGameData *savedGameData = [[MobSvcSavedGameData alloc] init];
        savedGameData.data = [NSString stringWithUTF8String:data];
        [mobSvcAccount saveGameData:[NSKeyedArchiver archivedDataWithRootObject:savedGameData] withName:[[NSString alloc] initWithUTF8String:name] completionHandler:^(GKSavedGame * _Nullable savedGame __unused, NSError * _Nullable error) {
            if(error == nil)
            {
                NSLog(@"Successfully uploaded saved game data");
            }
            else
            {
                NSLog(@"Failed to upload saved game data: %@", error.description);
            }
        }];
    }
}

И вот как я снова загружаю самую последнюю сохраненную игру во время следующей игровой сессии:

void MobSvc::downloadSavedGameDataAwait(const char *name)
{
    GKLocalPlayer *mobSvcAccount = [GKLocalPlayer localPlayer];

    if(mobSvcAccount.isAuthenticated)
    {
        [mobSvcAccount fetchSavedGamesWithCompletionHandler:^(NSArray<GKSavedGame *> * _Nullable savedGames, NSError * _Nullable error) {
            if(error == nil)
            {
                GKSavedGame *savedGameToLoad = nil;
                for(GKSavedGame *savedGame in savedGames) {
                    const char *sname = savedGame.name.UTF8String;
                    if(std::strcmp(sname, name) == 0)
                    {
                        if (savedGameToLoad == nil || savedGameToLoad.modificationDate < savedGame.modificationDate) {
                            savedGameToLoad = savedGame;
                        }
                    }
                }
                if(savedGameToLoad != nil) {
                    [savedGameToLoad loadDataWithCompletionHandler:^(NSData * _Nullable data, NSError * _Nullable error) {
                        if(error == nil)
                        {
                            MobSvcSavedGameData *savedGameData = [NSKeyedUnarchiver unarchiveObjectWithData:data];
                            NSLog(@"Successfully downloaded saved game data: %@", [savedGameData.data cStringUsingEncoding:NSUTF8StringEncoding]);
                        }
                        else
                        {
                            NSLog(@"Failed to download saved game data: %@", error.description);
                        }
                    }];
                }
            }
            else
            {
                NSLog(@"Failed to prepare saved game data: %@", error.description);
            }
        }];
    }
}

Я проверил это, загрузив случайную строку и получив ее в следующем сеансе, используя тот же name. Оно работает! Однако, как только я пытаюсь загрузить сохраненную игру со своего второго iPhone, она не работает. На обоих телефонах я вошел в одну и ту же учетную запись Game-Center, я мог подтвердить это, сравнив экземпляр playerId с экземпляром GKLocalPlayer.

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

Что здесь происходит? Как я могу поделиться сохраненной игрой на устройствах Apple?


person Martin Braun    schedule 24.10.2018    source источник


Ответы (1)


Приведенный выше образец в вопросе работает просто отлично. Обязательно, чтобы пользователь входил в iCloud и использовал тот же Apple ID при входе в Game Center, потому что сохраненные игры будут храниться в iCloud.

К сожалению, я тестировал все без iCloud, поэтому не получилось.

person Martin Braun    schedule 18.11.2018
comment
как вы разрешаете конфликты сохраненных игр с помощью fetchSavedGamesWithCompletionHandler? это означает более одной сохраненной игры с одним и тем же названием - person caochao; 25.04.2019