根据对我上一个问题的答案的建议,我编写了一些代码,允许从远程服务器加载我的游戏平衡属性。现在,为了简单起见,我只是在web服务器上托管原始属性列表文件。
我的第一个问题是,是否存在与以这种方式托管文件相关的长期问题。每当创建GameBalance对象时,用户将访问远程文件,但只有当版本高于保存到本地文档文件夹的版本时,才会下载该文件。
我的第二个问题是,在连接失败时,我是否提供了足够的保护,或者是否由于某些与internet相关的错误而下载了部分属性列表。包丢失和互联网协议在这里起作用了吗,他们会把这搞砸吗?
我的最后一个问题是,虽然我能够在普通C函数中完成初始化过程中发生的几乎所有工作,但我确实有一个对[self loadSettingsFromList]的调用。这是可以接受的,还是不好的做法?此方法唯一要做的事情是将值赋值给实例变量。
#pragma mark - Download Plist
int savedVersionNumber() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"ServerGameBalance.plist"];
NSDictionary *settingsList = [[NSDictionary alloc] initWithContentsOfFile:filePath];
return [settingsList[@"VersionId"]intValue];
}
int remoteVersionNumber() {
NSString *stringURL = @"http://192.168.1.1:80/DownloadedBalance.plist";
NSURL *url = [NSURL URLWithString:stringURL];
NSDictionary *settingsList = [NSDictionary dictionaryWithContentsOfURL:url];
return [settingsList[@"VersionId"]intValue];
}
void downloadPlistFromServerAndSave() {
NSString *stringURL = @"http://192.168.1.1:80/DownloadedBalance.plist";
NSURL *url = [NSURL URLWithString:stringURL];
NSData *urlData = [NSData dataWithContentsOfURL:url];
if (urlData) {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"ServerGameBalance.plist"];
[urlData writeToFile:filePath atomically:YES];
}
}
NSDictionary* downloadedPlist() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [NSString stringWithFormat:@"%@/%@", documentsDirectory,@"ServerGameBalance.plist"];
NSDictionary *settingsList = [[NSDictionary alloc] initWithContentsOfFile:filePath];
return settingsList[@"Settings"];
}#pragma mark - Initialization
-(id) init {
self = [super init];
if (self) {
//if it is zero then the internet could be down, or it is not valid anyway
if (remoteVersionNumber() != 0) {
//download a new plist if needed
if (remoteVersionNumber() > savedVersionNumber()) {
downloadPlistFromServerAndSave();
}
_listOfSettings = downloadedPlist();
} else {
_listOfSettings = localSettingsList();
}
[self loadSettingsFromList];
}
return self;
}
NSDictionary* localSettingsList() {
NSString *plistCatPath = [[NSBundle mainBundle] pathForResource:@"DTGameBalance" ofType:@"plist"];
NSDictionary *settingsList = [[NSDictionary alloc] initWithContentsOfFile:plistCatPath];
return settingsList[@"Settings"];
}
-(void) loadSettingsFromList {
_gameSettings = [_listOfSettings objectForKey:@"gameSettings"];
_towerSettings = [_listOfSettings objectForKey:@"towerSettings"];
_jobCostSettings = [_listOfSettings objectForKey:@"jobCostSettings"];
_roomCostSettings = [_listOfSettings objectForKey:@"roomCostSettings"];
}发布于 2014-08-15 23:06:20
这里有两个重要的大局需要把握。
首先,不只是为了检查版本号而下载整个plist,我们最好有一个单独的位置来检查版本号。我们所需要做的就是下载一个非常小的包并比较版本。然后我们只需要浪费带宽为用户和我们的服务器,如果那里的版本实际上是过时的。
其次,访问远程文件需要时间。访问远程文件也可能有错误。我们可能会完全找不到文件。而且,考虑到这些文件纯粹是游戏平衡的调整,我认为没有必要让用户在下载文件时等待。我们得把这次行动移到后台。
负责检查和获取更新的类也应该与已从文件中下载设置的类完全不同。
基本上,我们有一个给定的文件路径,我们存储我们的游戏平衡设置。在应用程序首次启动时,我们将plist复制到这个文件路径中。现在,当用户开始一个新游戏时,我们每次都从这个文件路径加载设置。同时,我们正在异步地寻找更新。如果我们发现有更新,我们下载更新的plist并将其写入预定的文件路径,在该路径中,我们知道其他类从其中获取设置。
因此,第一步是编写一些逻辑,将预包含的plist移动到可以覆盖它的文件路径。
第二步,将在线检查更新的所有逻辑移出从此文件路径加载设置的类。
第三步,创建一个用于检查联机更新的新类。
这是一大步。我们需要决定应用程序应该多久检查一次,并确保我们将课程安排在这个频率上。如果我今天播放你的应用程序6个小时,我的设备需要每10分钟检查一次吗?不太可能。你不太可能一天更新一次以上,对吧?而且你的游戏平衡调整也不太可能是任何需要立即调整的东西,对吗?见鬼,你甚至可以在游戏平衡设置中包含一个值来确定下一次的更新检查应该是什么时候。
但是当我们创建这个类时,我们实际上不应该在init方法中做很多事情。init方法实际上只应该做一件事:用当前版本的游戏初始化一个实例变量。
该类还应该具有一个只读NSDate属性,以存储其最后一次成功检查联机文件的时间戳。
现在,我们只提供一个方法,比如:fetchUpdates,它首先检查URL路径A,将当前版本与最新的在线版本进行比较,如果在线版本看起来更新,那么该方法将启动到URL路径B的连接,在那里它实际下载更新。
另外,我们希望编写类,这样它就有一个delegate来通知更新已经完成,或者我们的fetchUpdates方法应该采用一个完成块参数,一旦更新完成,它就会触发。
而不是使用NSData的S dataWithContentsOfURL:方法,我们需要使用一个NSURLConnection对象并使我们的类成为一个NSURLConnection委托,这样我们就可以异步地执行所有网络操作。
https://codereview.stackexchange.com/questions/60186
复制相似问题