三种方式使得iOS程序即使在关闭或崩溃的情况下也能够在后台持续进行一些任务,比如更新程序界面快照,下载文件等。这三个方法分别是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]; }

测试

  • 通过查看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 *)applicationdidReceiveRemoteNotification:(NSDictionary *)userInfofetchCompletionHandler:(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 *)sessiondownloadTask:(NSURLSessionDownloadTask *)downloadTaskdidFinishDownloadingToURL:(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 *)applicationhandleEventsForBackgroundURLSession:(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(); } }

原文地址 

转载于:https://www.cnblogs.com/pandas/p/4334871.html

三种方式使得iOS应用能够在后台进行数据更新和下载相关推荐

  1. IOS应用分发的三种方式

    IOS应用分发的三种方式 IOS应用分发三种方式 上架到AppStore 扫码或者点击链接下载安装 放到第三方应用内测分发平台 上架到AppStore 这个就不讲了,一句两句讲不清楚,网上教程一大堆, ...

  2. response设置编码的三种方式以及比较

    https://blog.csdn.net/u010653908/article/details/53994021 response设置编码的三种方式以及比较 2017年01月03日 14:12:46 ...

  3. Python实现微信支付(三种方式)

    Python实现微信支付(三种方式) 微信.支付宝二维码聚合SDK下载 点我下载 关注公众号"轻松学编程"了解更多. 如果需要python SDk源码,可以加我微信[1257309 ...

  4. ios 应用和电脑共享文件夹_堪比AirDrop,苹果 iPhone与Windows电脑互传文件的三种方式...

    如果你是苹果全家桶用户,一定会对 「AirDrop(隔空投送)」 功能赞誉有加,使用 AirDrop 可以在 iPhone 与 MacBook.iPad 等设备之间快速传递照片.视频或文件. 遗憾的是 ...

  5. ios多线程开发的常用三种方式

    ios多线程开发的常用三种方式 1.NSThread 2.NSOperationQueue 3.GCD NSThread: 创建方式主要有两种: [NSThread detachNewThreadSe ...

  6. ios网络学习------4 UIWebView的加载本地数据的三种方式

    ios网络学习------4 UIWebView的加载本地数据的三种方式 分类: IOS2014-06-27 12:56 959人阅读 评论(0) 收藏 举报 UIWebView是IOS内置的浏览器, ...

  7. iOS:延时执行的三种方式

    延时执行的三种方式:performSelectorXXX方法.GCD中延时函数.创建定时器 第一种方式:NSObject分类当中的方法,延迟一段时间调用某一个方法 @interface NSObjec ...

  8. 【iOS开发】ipa安装到手机上的三种方式

    转载地址:ipa安装到手机上的三种方式 ipa包 安装三种方式,优先推荐第一种方法(通过iTunes安装). 1.通过iTunes安装 数据线连接手机之后,会自动连接iTunes,(第一次连接的时候会 ...

  9. 盛大游戏技术总监徐峥:Unity引擎使用的三种方式

    在5月13日Unite 2017 案例分享专场上,盛大游戏技术总监徐峥分享了使用Unity引擎的三种方式,以下为详细内容: 大家好,我先简单介绍一下我自己,我是盛大游戏的技术总监徐峥.我今天想分享的主 ...

最新文章

  1. 贝壳大数据OLAP平台架构演进
  2. SQL中游标的使用(转)
  3. Sqluldr2 libclntsh.so报错处理
  4. SAP CRM Reference类型下拉菜单里的值是从哪里取出的
  5. Dotnet Core下的Channel, 你用了吗?
  6. Apollo的基本概念和集成实战
  7. poj 1279 Art Gallery - 求多边形核的面积
  8. python学什么东西_什么是Python?你应该学习和使用它的13个理由
  9. POJ 2635 The Embarrassed Cryptographer(JAVA)
  10. css3 修改checkbox disabled颜色_HTML5 + CSS3 gt;gt;gt; 009
  11. Chrome下可用的的Kubernetes Dashboard证书的制作
  12. OSS对象存储是什么?
  13. 什么是动态DNS(DDNS)
  14. 【JavaSE进阶(上)】自学笔记 记得收藏时时回顾
  15. 我的自学全栈路(从0元自学到转行IT)
  16. 实战 | 安服仔用一毛钱维修台伊拉克成色笔记本(上)
  17. c语言要使用数学函数,c语言中用到的 数学函数(转)
  18. 【服务器数据恢复】存储之间迁移数据时数据损坏的数据恢复案例
  19. json.stringify()函数
  20. LATEX公式行间距调整

热门文章

  1. 调试 SharePoint 解决方案
  2. Linux 下, npm i 老是被killed 已杀死
  3. 使用log4Net 输出日志到mongodb
  4. 软件设计和设计的问题
  5. php 转码iconv,PHP iconv()函数转字符编码的问题(转)
  6. 调用接口登录禅道_有java调用api登录并验证禅道的实例吗
  7. .net开发是做什么的_软件开发是什么, 该怎么做?
  8. WebService C#开发/调用
  9. 电商企业怎样用好大数据
  10. css_oneday