iOS7后台数据下载教程
2013-12-26 16:30
567 查看
原文:iOS 7 SDK: Background Transfer Service
这个教程将会教会你如何在后台传输数据,如何使用iOS7提供的多任务API。我将会教会你如何在后台下载一个文件,并且在文件下载完成时弹出一个本地的提醒。 后台数据传输起源于iOS6,允许在前台或者后台下载数据,但是时间是受限制的。最大的问题就是时间是受限制的让用户无法上传或下载大文件。这就是为什么苹果在iOS7上要提升框架的原因。 在iOS7中,这个功能有了很大变化,包括:
1.iOS系统管理上传和下载任务。
2.当用户关闭应用程序时后台仍然可以传输数据
3.时间不受限制
4.它可以在任意时间加入队列(前台或者后台)
5.应用程序需要被唤醒来获取验证,错误,或者完成情况
6.应用程序会有一个进度展示视图 后台传输可以应用在几个非常有用的地方:上传照片或者视频,结合后台提取和远程通知,用于保持应用程序在最新时间。
下面是范例工程。
注:原文,作者是去下载了一个PDF,由于下载的苹果那个PDF感觉比较慢,就改成下载我自己服务器上的一个mp3文件了。
1.创建工程 我们需要一个MainViewController来做这里的主要工作:
1)包含一个按钮,一个ProgeressView
像这样:
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/Snip20131213_3-219x300.png)
然后,我们需要在工程头文件里面添加我们需要的成员。
完成之后,我们的MainViewController.h会像这样
下一步我们需要使用NSURLSession来完成任务。
我们要在viewDidLoad中初始化我们需要的session成员
然后我们要完成一个单一的session,使用dispatch_once来确保它会是同一个对象,里面有个要点,请仔细看注释
我们再给开始按钮方法添加开始下载任务的执行
再接着我们需要来完成最重要的事情,把Session的代理方法完成
首先我们完成 NSURLSessionDownloadTaskDelegate
接着我们需要完成NSURLSessionTaskDelegate需要用到的代理方法
最后,我们要完成NSURLSessionDelegate代理方法
这里我们用到了AppDelegate里面的一个成员block,用来执行当后台下载完成时调度这个方法。所以我们还要去完成我们的AppDelegate
我们在AppDelegate.h里面添加一个完成时执行的block,添加完应该是这样的
然后,我们去AppDelegate.m里面完成我们需要弹出本地提醒的方法就大功告成了!
在AppDelegate.m里面,我们需要完成下面几个重要的方法:
添加完应该是这样的
我们最后需要当用户点击进来时,把图标上面的数字提醒设置为0
最终我们运行效果会是这样的:
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.29.58%E2%80%9D-169x300.png)
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.30.34%E2%80%9D-169x300.png)
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.30.44%E2%80%9D-169x300.png)
最后的最后是工程的源代码了:
ZYBackgroundService
background transfer,
iOS后台下载,iOS7,
NSURLSession
这个教程将会教会你如何在后台传输数据,如何使用iOS7提供的多任务API。我将会教会你如何在后台下载一个文件,并且在文件下载完成时弹出一个本地的提醒。 后台数据传输起源于iOS6,允许在前台或者后台下载数据,但是时间是受限制的。最大的问题就是时间是受限制的让用户无法上传或下载大文件。这就是为什么苹果在iOS7上要提升框架的原因。 在iOS7中,这个功能有了很大变化,包括:
1.iOS系统管理上传和下载任务。
2.当用户关闭应用程序时后台仍然可以传输数据
3.时间不受限制
4.它可以在任意时间加入队列(前台或者后台)
5.应用程序需要被唤醒来获取验证,错误,或者完成情况
6.应用程序会有一个进度展示视图 后台传输可以应用在几个非常有用的地方:上传照片或者视频,结合后台提取和远程通知,用于保持应用程序在最新时间。
下面是范例工程。
注:原文,作者是去下载了一个PDF,由于下载的苹果那个PDF感觉比较慢,就改成下载我自己服务器上的一个mp3文件了。
1.创建工程 我们需要一个MainViewController来做这里的主要工作:
1)包含一个按钮,一个ProgeressView
像这样:
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/Snip20131213_3-219x300.png)
然后,我们需要在工程头文件里面添加我们需要的成员。
完成之后,我们的MainViewController.h会像这样
#import <AVFoundation/AVFoundation.h> @interface MainViewController : UIViewController<NSURLSessionDelegate,NSURLSessionTaskDelegate,NSURLSessionDownloadDelegate,UIDocumentInteractionControllerDelegate> @property (weak, nonatomic) IBOutlet UIProgressView *progressView; @property (nonatomic)NSURLSession *session; @property (nonatomic)NSURLSessionDownloadTask *downloadTask; @property (strong,nonatomic)UIDocumentInteractionController *documentInteractionController; @property (nonatomic,strong)AVPlayer *player; - (IBAction)startDownload:(id)sender;
下一步我们需要使用NSURLSession来完成任务。
我们要在viewDidLoad中初始化我们需要的session成员
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.session = [self backgroundSession]; self.progressView.progress = 0; self.progressView.hidden = YES; }
然后我们要完成一个单一的session,使用dispatch_once来确保它会是同一个对象,里面有个要点,请仔细看注释
- (NSURLSession *)backgroundSession { static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ //这个sessionConfiguration 很重要, com.zyprosoft.xxx 这里,这个com.company.这个一定要和 bundle identifier 里面的一致,否则ApplicationDelegate 不会调用handleEventsForBackgroundURLSession代理方法 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"com.zyprosoft.backgroundsession"]; session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; }); return session; }
我们再给开始按钮方法添加开始下载任务的执行
- (IBAction)startDownload:(id)sender { if (self.downloadTask) { return; } NSURL *downloadURL = [NSURL URLWithString:DownloadURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; self.downloadTask = [self.session downloadTaskWithRequest:request]; [self.downloadTask resume]; self.progressView.hidden = NO; }
再接着我们需要来完成最重要的事情,把Session的代理方法完成
首先我们完成 NSURLSessionDownloadTaskDelegate
//这个方法用来跟踪下载数据并且根据进度刷新ProgressView - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { if (downloadTask == self.downloadTask) { double progress = (double)totalBytesWritten / (double)totalBytesExpectedToWrite; NSLog(@"下载任务: %@ 进度: %lf", downloadTask, progress); dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); } } //下载任务完成,这个方法在下载完成时触发,它包含了已经完成下载任务得 Session Task,Download Task和一个指向临时下载文件得文件路径 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *URLs = [fileManager URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask]; NSURL *documentsDirectory = [URLs objectAtIndex:0]; NSURL *originalURL = [[downloadTask originalRequest] URL]; NSURL *destinationURL = [documentsDirectory URLByAppendingPathComponent:[originalURL lastPathComponent]]; NSError *errorCopy; // For the purposes of testing, remove any esisting file at the destination. [fileManager removeItemAtURL:destinationURL error:NULL]; BOOL success = [fileManager copyItemAtURL:location toURL:destinationURL error:&errorCopy]; if (success) { dispatch_async(dispatch_get_main_queue(), ^{ //download finished - open the pdf //原文下载的苹果的pdf,感觉有点慢,自己又没找到比较大一点的pdf,干脆就放了个mp3歌曲在自己服务器上,所以下载完就播放mp3吧 // self.documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:destinationURL]; // // Configure Document Interaction Controller // [self.documentInteractionController setDelegate:self]; // // Preview PDF // [self.documentInteractionController presentPreviewAnimated:YES]; // self.progressView.hidden = YES; //播放音乐 self.player = [AVPlayer playerWithURL:destinationURL]; [self.player play]; }); } else { NSLog(@"复制文件发生错误: %@", [errorCopy localizedDescription]); } } //这个方法我们暂时用不上 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { }
接着我们需要完成NSURLSessionTaskDelegate需要用到的代理方法
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if (error == nil) { NSLog(@"任务: %@ 成功完成", task); } else { NSLog(@"任务: %@ 发生错误: %@", task, [error localizedDescription]); } double progress = (double)task.countOfBytesReceived / (double)task.countOfBytesExpectedToReceive; dispatch_async(dispatch_get_main_queue(), ^{ self.progressView.progress = progress; }); self.downloadTask = nil; }
最后,我们要完成NSURLSessionDelegate代理方法
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { ZYBackgroundServiceAppDelegate *appDelegate = (ZYBackgroundServiceAppDelegate *)[[UIApplication sharedApplication] delegate]; if (appDelegate.backgroundSessionCompletionHandler) { void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler; appDelegate.backgroundSessionCompletionHandler = nil; completionHandler(); } NSLog(@"所有任务已完成!"); }
这里我们用到了AppDelegate里面的一个成员block,用来执行当后台下载完成时调度这个方法。所以我们还要去完成我们的AppDelegate
我们在AppDelegate.h里面添加一个完成时执行的block,添加完应该是这样的
@interface ZYBackgroundServiceAppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @property (copy) void (^backgroundSessionCompletionHandler)(); @end
然后,我们去AppDelegate.m里面完成我们需要弹出本地提醒的方法就大功告成了!
在AppDelegate.m里面,我们需要完成下面几个重要的方法:
添加完应该是这样的
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; //初始化 MainViewController *mainViewController = [[MainViewController alloc]initWithNibName:@"MainViewController" bundle:Nil]; mainViewController.title = @"后台下载测试Demo"; UINavigationController *rootNav = [[UINavigationController alloc]initWithRootViewController:mainViewController]; self.window.rootViewController = rootNav; [self.window makeKeyAndVisible]; return YES; } - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { self.backgroundSessionCompletionHandler = completionHandler; //添加本地通知 [self presentNotification]; } -(void)presentNotification{ UILocalNotification* localNotification = [[UILocalNotification alloc] init]; localNotification.alertBody = @"下载完成!"; localNotification.alertAction = @"后台传输下载已完成!"; //提示音 localNotification.soundName = UILocalNotificationDefaultSoundName; //icon提示加1 localNotification.applicationIconBadgeNumber = [[UIApplication sharedApplication] applicationIconBadgeNumber] + 1; [[UIApplication sharedApplication] presentLocalNotificationNow:localNotification]; }
我们最后需要当用户点击进来时,把图标上面的数字提醒设置为0
- (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. application.applicationIconBadgeNumber = 0; }
最终我们运行效果会是这样的:
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.29.58%E2%80%9D-169x300.png)
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.30.34%E2%80%9D-169x300.png)
![](http://www.zyprosoft.com/wp-content/uploads/2013/12/iOS-%E6%A8%A1%E6%8B%9F%E5%99%A8%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7%E2%80%9C2013%E5%B9%B412%E6%9C%8813%E6%97%A5-%E4%B8%8B%E5%8D%885.30.44%E2%80%9D-169x300.png)
最后的最后是工程的源代码了:
ZYBackgroundService
background transfer,
iOS后台下载,iOS7,
NSURLSession
相关文章推荐
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- Discuz!教程之应用中心安装插件提示“数据下载错误(105)”的解决办法
- tensorflow教程中的mnist数据下载脚本
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- iOS后台进行数据更新和下载
- 批量从NCBI后台下载指定数据的Perl脚本
- tensorflow教程中的mnist数据下载脚本
- 资源下载南方cass视频教程,包括文档,数据,很全的
- EXCEL 宏 拆分数据表 VBA 视频教程下载
- 用ajax提交数据到后台以便下载,但是不能下载
- Yeslab现任明教教主数据中心第二门课程UCS 视频教程下载
- ASP_NET 2_0数据教程.chm 下载(26.15 MB)
- 数据挖掘视频教程全集下载
- Tensorflow教程-MNIST 数据下载
- 斯坦福大学公开课IOS7视频教程百度网盘下载
- python后台架构Django教程——数据模型Model
- Android 解析后台返回为Json数据实例教程
- 为什么 iOS 上有些应用可后台下载数据,而有些不能 ?
- 4000 caffe 教程 Fine-tuning a Pretrained Network for Style Recognition下载数据
- 一款靓丽的html5后台管理模板代码下载,适合开发者进行后台数据开发