iOS后台进行数据更新和下载
2017-03-18 10:32
309 查看
三种方式使得iOS程序即使在关闭或崩溃的情况下也能够在后台持续进行一些任务,比如更新程序界面快照,下载文件等。这三个方法分别是
开启
首先在info plist文件中开启UIBackgroundModes的Background fetch。或者手动编辑这个值
iOS默认不进行background fetch,需要设置一个时间的间隔
最后在App Delegate里实现下面的方法,这个方法只能在30秒内完成。
测试
4000
通过查看UIApplication的applicationState
Remote Notification
在普通的远程通知里带上content-available标志就可以在通知用户同时在后台进行更新。通知结构如下
接收一条带有content-available的通知会调用下面的方法
利用NSURLSession进行background transfer task
使用[NSURLSessionConfiguration backgroundSessionConfiguration]创建一个后台任务,当应用退出后,崩溃或进程被关掉都还是会运行。
范例,先处理一条远程通知,并将NSURLSessionDownloadTask添加到后台传输服务队列。
下载完成后调用NSURLSessionDownloadDelegate的委托方法,这些委托方法全部是必须实现的。了解所有类型session task的生命周期可以参考官方文档:https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html#//apple_ref/doc/uid/10000165i-CH2-SW42
Background Fetch,Remote Notification和NSURLSession的backgroundSessionConfiguration
Background Fetch
开启
首先在info plist文件中开启UIBackgroundModes的Background fetch。或者手动编辑这个值
<key>UIBackgroundModes</key> <array> <string>fetch</string> </array>
iOS默认不进行background fetch,需要设置一个时间的间隔
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //UIApplicationBackgroundFetchIntervalMinimum表示尽可能频繁去获取,如果需要指定至少多少时间更新一次就需要给定一个时间值 [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum]; return YES; }
最后在App Delegate里实现下面的方法,这个方法只能在30秒内完成。
- (void) application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration]; NSURL *url = [[NSURL alloc] initWithString:@"http://yourserver.com/data.json"]; NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { if (error) { completionHandler(UIBackgroundFetchResultFailed); return; } // 解析响应/数据以决定新内容是否可用 BOOL hasNewData = ... if (hasNewData) { completionHandler(UIBackgroundFetchResultNewData); } else { completionHandler(UIBackgroundFetchResultNoData); } }]; // 开始任务 [task resume]; }
测试
4000
通过查看UIApplication的applicationState
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"Launched in background %d", UIApplicationStateBackground == application.applicationState); return YES; }
Remote Notification
在普通的远程通知里带上content-available标志就可以在通知用户同时在后台进行更新。通知结构如下
{ "aps" : { "content-available" : 1 }, "content-id" : 42 }
接收一条带有content-available的通知会调用下面的方法
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSLog(@"Remote Notification userInfo is %@", userInfo); NSNumber *contentID = userInfo[@"content-id"]; // 根据 content ID 进行操作 completionHandler(UIBackgroundFetchResultNewData); }
利用NSURLSession进行background transfer task
使用[NSURLSessionConfiguration backgroundSessionConfiguration]创建一个后台任务,当应用退出后,崩溃或进程被关掉都还是会运行。
范例,先处理一条远程通知,并将NSURLSessionDownloadTask添加到后台传输服务队列。
- (NSURLSession *)backgroundURLSession { static NSURLSession *session = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ NSString *identifier = @"io.objc.backgroundTransferExample"; NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier]; session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]]; }); return session; } - (void) application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { NSLog(@"Received remote notification with userInfo %@", userInfo); NSNumber *contentID = userInfo[@"content-id"]; NSString *downloadURLString = [NSString stringWithFormat:@"http://yourserver.com/downloads/%d.mp3", [contentID intValue]]; NSURL* downloadURL = [NSURL URLWithString:downloadURLString]; NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL]; NSURLSessionDownloadTask *task = [[self backgroundURLSession] downloadTaskWithRequest:request]; task.taskDescription = [NSString stringWithFormat:@"Podcast Episode %d", [contentID intValue]]; //执行resume保证开始了任务 [task resume]; completionHandler(UIBackgroundFetchResultNewData); }
下载完成后调用NSURLSessionDownloadDelegate的委托方法,这些委托方法全部是必须实现的。了解所有类型session task的生命周期可以参考官方文档:https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html#//apple_ref/doc/uid/10000165i-CH2-SW42
#Pragma Mark - NSURLSessionDownloadDelegate
- (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"downloadTask:%@ didFinishDownloadingToURL:%@", downloadTask.taskDescription, location); // 必须用 NSFileManager 将文件复制到应用的存储中,因为临时文件在方法返回后会被删除 // ... // 通知 UI 刷新 } - (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes { } - (void) URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { } 后台的任务完成后如果应用没有在前台运行,需要实现UIApplication的两个delegate让系统唤醒应用 - (void) application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { // 你必须重新建立一个后台 seesiong 的参照 // 否则 NSURLSessionDownloadDelegate 和 NSURLSessionDelegate 方法会因为 // 没有 对 session 的 delegate 设定而不会被调用。参见上面的 backgroundURLSession NSURLSession *backgroundSession = [self backgroundURLSession]; NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession); // 保存 completion handler 以在处理 session 事件后更新 UI [self addCompletionHandler:completionHandler forSession:identifier]; } - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { NSLog(@"Background URL session %@ finished events. ", session); if (session.configuration.identifier) { // 调用在 -application:handleEventsForBackgroundURLSession: 中保存的 handler [self callCompletionHandlerForSession:session.configuration.identifier]; } } - (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier { if ([self.completionHandlerDictionary objectForKey:identifier]) { NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen. "); } [self.completionHandlerDictionary setObject:handler forKey:identifier]; } - (void)callCompletionHandlerForSession: (NSString *)identifier { CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey: identifier]; if (handler) { [self.completionHandlerDictionary removeObjectForKey: identifier]; NSLog(@"Calling completion handler for session %@", identifier); handler(); } }
相关文章推荐
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- ios开发——日常之三种方式使得iOS应用能够在后台进行数据更新和下载
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- 三种方式使得iOS应用能够在后台进行数据更新和下载
- 后台进行数据更新和下载
- 后台进行数据更新和下载
- 为什么 iOS 上有些应用可后台下载数据,而有些不能 ?
- iOS使用NSURLSession进行下载(包括后台下载,断点下载)
- 如何将VFP本地表数据传送到SQL-Server后台进行更新
- 定期iOS的后台位置更新-- 相关资料收集,待有时间进行整理
- 一款靓丽的html5后台管理模板代码下载,适合开发者进行后台数据开发
- 用LINQ to SQL 进行数据访问、更新和删除(附Demo示例程序下载)
- Unity+IOS GPS后台更新GPS数据
- 用a标签传数据给后台进行表格下载遇到的问题
- iOS 下载图片 -当后台返回的数据是文件流而不是图片url
- iOS 后台返回的HTML数据怎么解析
- socket iOS 与java 后台进行socket通讯遇到的问题以及解决方法