objective-c - 如何跨设备共享保存的游戏?
问题描述
我在我的 iOS 游戏中实现了 GameKit,包括保存的游戏功能。
这是我如何保存和加载游戏的示例:
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 设备之间共享保存的游戏?
解决方案
问题中的上述示例工作得很好。用户必须登录 iCloud 并在 Game Center 登录时使用相同的 Apple ID,因为保存的游戏将存储在 iCloud 中。
不幸的是,我在没有 iCloud 的情况下测试了整个系统,所以它无法工作。
推荐阅读
- javascript - 因此返回一个 JSX 必然会使函数成为一个组件?
- typescript - NPM 仅安装后依赖项
- javascript - 污染的画布 - 但仅在一台 Windows 10 Chrome PC 上
- python - 我需要一个类似于 pygtrie.PrefixSet 在 python 中的 PrefixMap
- java - KafkaConsumer.commitSync/commitAsync 是否可以提交未分配分区的偏移量
- docker - Docker 通过 ssh 连接到远程守护进程 - 权限被拒绝(公钥)
- prometheus - 两个具有相同数据存储库的 Prometheus
- javascript - 垃圾收集内联事件
- activemq - 有没有办法以编程方式删除 ActiveMQ 作业计划?
- java - Spring Boot 中枚举的通用 AttributeConverter