从服务器下载plist

今天我有一个应用程序读取plist站点,但它会像这样工作:

当您打开应用程序时,它会检查用户是否已在设备上安装了plist,以及是否为最新版本。

如果您没有,它是最新版本的服务器捕获

http://lab.vpgroup.com.br/aplicativos/teste-catalogo/lista.plist

我怎么能这样做? 我在stackoverflow上看到了很多问题,但没有一个能按我的需要工作。

谢谢

你永远不想阻止用户界面。 下载可能需要很长时间。 因此在后台做。 最简单的是使用NSURLConnection的便捷方法sendAsynchronousRequest:request就像名字所说的那样,它是异步的,并在下载完成时调用传递的完成块

 NSURL *url = [NSURL URLWithString:@"http://lab.vpgroup.com.br/aplicativos/teste-catalogo/lista.plist"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dict = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:0 errorDescription:nil]; NSLog(@"%@", dict); }]; 

样品:

 #import  int main(int argc, char *argv[]) { @autoreleasepool { NSURL *url = [NSURL URLWithString:@"http://lab.vpgroup.com.br/aplicativos/teste-catalogo/lista.plist"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dict = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:0 errorDescription:nil]; NSLog(@"%@", dict); }]; //just for demo [[NSRunLoop currentRunLoop] run]; } } 

您可以对路径进行HEAD调用,并获取将存储在设备上的Etag,如果设备上保存的etag不等于服务器发送的etag,则下载文件,存储新的Etag并覆盖设备文件。 您也可以使用Last-Modified:标头,但etag可能是最好的。 您可能需要在服务器上启用实体标记。

为了澄清,HEAD只发送文件的标题,因此通常比发送整个文件的重量要轻得多。

这就是浏览器如何管理静态文件和URL的本地缓存,在这种情况下,浏览器发送他们的Etag,浏览器返回304未经修改,所以你也可以考虑复制这个发送你存储的etag协议并让浏览器返回文件或304标题。

我只是回复你可以使用什么策略,而不是你如何实现,同步或asyn取决于它正在使用的上下文。

我的建议是按照上面Diaj-Djan的建议向NSOperationque添加一个请求。

回答如何做到这一点:有几种方法可以实现:

  1. 选项1:如果您可以向plist文件添加属性,请说出Version和如果您可以公开一个向您发送版本号的服务。 其他选项2.您第一次明显下载plist文件,并按照您希望的方式在您的设备上保留该版本。 在随后的下载 – >第一步检查来自设备的持久版本,看看服务器中是否有新版本可用于公开的服务 – >如果是 – >进行服务调用以获取plist文件 – >否使用设备中的那个。 这样,每次下载一个plist(特别是如果它的巨大),你可以节省大量的时间/数据下载

  2. 选项2:您每次都进行一次服务调用,获取plist文件,比较属性并查看是否有任何更改。 这不是一个好的选择,它耗费时间,处理很多。

我使用@ daij-Djan去上面创建的基础,工作得很好。就像这样:

在我的。 h #import

 @interface ViewController : UIViewController{ NSArray *paths; NSString *documentsDirectory; NSString *myPathDocs; NSFileManager *fileManager; NSString *filePath; NSString *documentsPath; NSURL *url; } 

在我的。 米

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); documentsDirectory = [paths objectAtIndex:0]; //filename that will save in device filePath = [documentsDirectory stringByAppendingPathComponent:@"lista.plist"]; [self showData]; [self updatingData]; } - (void) updatingData { NSLog(@"updating Data"); url = [NSURL URLWithString:@"http://lab.vpgroup.com.br/aplicativos/teste-catalogo/lista.plist"]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { NSDictionary *dict = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:0 format:0 errorDescription:nil]; NSLog(@"%@", dict); @try { [dict writeToFile:filePath atomically:YES]; NSLog(@"Saved!! path: %@", filePath); } @catch (NSException *exception) { NSLog(@"Error writing. Erro: %@", [exception description]); } [self showData]; }]; } - (void) showData { NSString *pathFinal = filePath; if (![[NSFileManager defaultManager] fileExistsAtPath:filePath]) { // if failed to get the plist server uses the local built pathFinal = [[NSBundle mainBundle] pathForResource:@"lista" ofType:@"plist"]; } NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:pathFinal]; NSLog(@"data displayed: %@", dict); }