三种方式使得iOS程序即使在关闭或崩溃的情况下也能够在后台持续进行一些任务,比如更新程序界面快照,下载文件等。这三个方法分别是 Background Fetch,Remote Notification和NSURLSession的backgroundSessionConfiguration

Background Fetch

开启

首先在info plist文件中开启UIBackgroundModes的Background fetch。或者手动编辑这个值

  1. <key>UIBackgroundModes</key>
  2. <array>
  3. <string>fetch</string>
  4. </array>

iOS默认不进行background fetch,需要设置一个时间的间隔

  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  2. {
  3. //UIApplicationBackgroundFetchIntervalMinimum表示尽可能频繁去获取,如果需要指定至少多少时间更新一次就需要给定一个时间值
  4. [application setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
  5. return YES;
  6. }

最后在App Delegate里实现下面的方法,这个方法只能在30秒内完成。

  1. - (void) application:(UIApplication *)application
  2. performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
  3. {
  4. NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
  5. NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
  6.  
  7. NSURL *url = [[NSURL alloc] initWithString:@"http://yourserver.com/data.json"];
  8. NSURLSessionDataTask *task = [session dataTaskWithURL:url
  9. completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
  10.  
  11. if (error) {
  12. completionHandler(UIBackgroundFetchResultFailed);
  13. return;
  14. }
  15.  
  16. // 解析响应/数据以决定新内容是否可用
  17. BOOL hasNewData = ...
  18. if (hasNewData) {
  19. completionHandler(UIBackgroundFetchResultNewData);
  20. } else {
  21. completionHandler(UIBackgroundFetchResultNoData);
  22. }
  23. }];
  24.  
  25. // 开始任务
  26. [task resume];
  27. }

测试

  • 通过查看UIApplication的applicationState
  1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
  2. {
  3. NSLog(@"Launched in background %d", UIApplicationStateBackground == application.applicationState);
  4.  
  5. return YES;
  6. }

Remote Notification

在普通的远程通知里带上content-available标志就可以在通知用户同时在后台进行更新。通知结构如下

  1. {
  2. "aps" : {
  3. "content-available" : 1
  4. },
  5. "content-id" : 42
  6. }

接收一条带有content-available的通知会调用下面的方法

  1. - (void)application:(UIApplication *)application
  2. didReceiveRemoteNotification:(NSDictionary *)userInfo
  3. fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
  4. {
  5. NSLog(@"Remote Notification userInfo is %@", userInfo);
  6.  
  7. NSNumber *contentID = userInfo[@"content-id"];
  8. // 根据 content ID 进行操作
  9. completionHandler(UIBackgroundFetchResultNewData);
  10. }

利用NSURLSession进行background transfer task

使用[NSURLSessionConfiguration backgroundSessionConfiguration]创建一个后台任务,当应用退出后,崩溃或进程被关掉都还是会运行。

范例,先处理一条远程通知,并将NSURLSessionDownloadTask添加到后台传输服务队列。

  1. - (NSURLSession *)backgroundURLSession
  2. {
  3. static NSURLSession *session = nil;
  4. static dispatch_once_t onceToken;
  5. dispatch_once(&onceToken, ^{
  6. NSString *identifier = @"io.objc.backgroundTransferExample";
  7. NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
  8. session = [NSURLSession sessionWithConfiguration:sessionConfig
  9. delegate:self
  10. delegateQueue:[NSOperationQueue mainQueue]];
  11. });
  12.  
  13. return session;
  14. }
  15.  
  16. - (void) application:(UIApplication *)application
  17. didReceiveRemoteNotification:(NSDictionary *)userInfo
  18. fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler
  19. {
  20. NSLog(@"Received remote notification with userInfo %@", userInfo);
  21.  
  22. NSNumber *contentID = userInfo[@"content-id"];
  23. NSString *downloadURLString = [NSString stringWithFormat:@"http://yourserver.com/downloads/%d.mp3", [contentID intValue]];
  24. NSURL* downloadURL = [NSURL URLWithString:downloadURLString];
  25.  
  26. NSURLRequest *request = [NSURLRequest requestWithURL:downloadURL];
  27. NSURLSessionDownloadTask *task = [[self backgroundURLSession] downloadTaskWithRequest:request];
  28. task.taskDescription = [NSString stringWithFormat:@"Podcast Episode %d", [contentID intValue]];
  29. //执行resume保证开始了任务
  30. [task resume];
  31.  
  32. completionHandler(UIBackgroundFetchResultNewData);
  33. }

下载完成后调用NSURLSessionDownloadDelegate的委托方法,这些委托方法全部是必须实现的。了解所有类型session task的生命周期可以参考官方文档:https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/URLLoadingSystem/NSURLSessionConcepts/NSURLSessionConcepts.html#//apple_ref/doc/uid/10000165i-CH2-SW42

  1. #Pragma Mark - NSURLSessionDownloadDelegate
  2.  
  3. - (void) URLSession:(NSURLSession *)session
  4. downloadTask:(NSURLSessionDownloadTask *)downloadTask
  5. didFinishDownloadingToURL:(NSURL *)location
  6. {
  7. NSLog(@"downloadTask:%@ didFinishDownloadingToURL:%@", downloadTask.taskDescription, location);
  8.  
  9. // 必须用 NSFileManager 将文件复制到应用的存储中,因为临时文件在方法返回后会被删除
  10. // ...
  11.  
  12. // 通知 UI 刷新
  13. }
  14.  
  15. - (void) URLSession:(NSURLSession *)session
  16. downloadTask:(NSURLSessionDownloadTask *)downloadTask
  17. didResumeAtOffset:(int64_t)fileOffset
  18. expectedTotalBytes:(int64_t)expectedTotalBytes
  19. {
  20. }
  21.  
  22. - (void) URLSession:(NSURLSession *)session
  23. downloadTask:(NSURLSessionDownloadTask *)downloadTask
  24. didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten
  25. totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
  26. {
  27. }

后台的任务完成后如果应用没有在前台运行,需要实现UIApplication的两个delegate让系统唤醒应用

  1. - (void) application:(UIApplication *)application
  2. handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
  3. {
  4. // 你必须重新建立一个后台 seesiong 的参照
  5. // 否则 NSURLSessionDownloadDelegate 和 NSURLSessionDelegate 方法会因为
  6. // 没有 对 session 的 delegate 设定而不会被调用。参见上面的 backgroundURLSession
  7. NSURLSession *backgroundSession = [self backgroundURLSession];
  8.  
  9. NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession);
  10.  
  11. // 保存 completion handler 以在处理 session 事件后更新 UI
  12. [self addCompletionHandler:completionHandler forSession:identifier];
  13. }
  14.  
  15. - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
  16. {
  17. NSLog(@"Background URL session %@ finished events.
  18. ", session);
  19.  
  20. if (session.configuration.identifier) {
  21. // 调用在 -application:handleEventsForBackgroundURLSession: 中保存的 handler
  22. [self callCompletionHandlerForSession:session.configuration.identifier];
  23. }
  24. }
  25.  
  26. - (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString *)identifier
  27. {
  28. if ([self.completionHandlerDictionary objectForKey:identifier]) {
  29. NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen.
  30. ");
  31. }
  32.  
  33. [self.completionHandlerDictionary setObject:handler forKey:identifier];
  34. }
  35.  
  36. - (void)callCompletionHandlerForSession: (NSString *)identifier
  37. {
  38. CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey: identifier];
  39.  
  40. if (handler) {
  41. [self.completionHandlerDictionary removeObjectForKey: identifier];
  42. NSLog(@"Calling completion handler for session %@", identifier);
  43.  
  44. handler();
  45. }
  46. }
 

转载地址:http://www.starming.com/index.php?v=index&view=69

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

  1. iOS字体加载三种方式

    静态加载 动态加载 动态下载苹果提供的多种字体 其他 打印出当前所有可用的字体 检查某字体是否已经下载 这是一篇很简短的文章,介绍了 iOS 自定义字体加载的三种方式. 静态加载 这个可以说是最简单最 ...

  2. iOS --- UIWebView的加载本地数据的三种方式

    UIWebView是IOS内置的浏览器,可以浏览网页,打开文档  html/htm  pdf   docx  txt等格式的文件.  safari浏览器就是通过UIWebView做的. 服务器将MIM ...

  3. iOS拨打电话的三种方式

    iOS拨打电话的三种方式 1,这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示 1 2 var string = "tel:" + "1 ...

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

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

  5. IOS 多线程,线程同步的三种方式

    本文主要是讲述 IOS 多线程,线程同步的三种方式,更多IOS技术知识,请登陆疯狂软件教育官网. 一般情况下我们使用线程,在多个线程共同访问同一块资源.为保护线程资源的安全和线程访问的正确性. 在IO ...

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

    UIWebView这是IOS内置的浏览器.能够浏览网页,打开文档  html/htm  pdf   docx  txt等待格文档类型. safari浏览器是通过UIWebView制作. server将 ...

  7. iOS开发 跳转场景的三种方式

    iOS开发 跳转场景的三种方式 2012年10月17日, 15:32 假设A跳转到B,三种方法:1.按住ctrl键,拖动A上的控件(比如说UIButton)到B上,弹出菜单,选择Modal.不需要写任 ...

  8. iOS-Core Foundation框架到Foundation桥接的三种方式

    温故知新.勤总结,才能生巧!这次总结一下 :Core Foundation框架到Foundation桥接的三种方式 Foundation提供OC的基础类(像NSObject).基本数据类型等. Cor ...

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

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

随机推荐

  1. μC/OS中的任务就绪表

    为了便于对就绪表的查找,μC/OSII又定义了一个数据类型为INT8U的变量OSRdyGrp, 并使该变量的每一位都对应OSRdyTbl[ ]的一个任务组(即数组的一个元素),如果某任务组中 有任务就 ...

  2. 1.Python字符编码

    1.编码简介 编码的种类情况 ASCII 占1个字节,只支持英文 GB2312 占2个字节,支持6700+汉字 GBK GB2312的升级版,支持21000+汉字 ks_c_5601-1987 韩国编 ...

  3. RMAN冷备份、一致性备份脚本

    RMAN冷备份.一致性备份脚本 run{ shutdown immediate; startup mount; allocate channel c1 type disk; allocate chan ...

  4. 使用mybatis generator 生成annotation形式的mapper

    最近使用mybatisgenerator时,希望生成annotation的mapper,在网上基本桑没有相关配置,记录,做以下记录: <?xml version="1.0"  ...

  5. (6)uboot具体解释——关闭缓存和mmu

    uboot具体解释--关闭缓存和mmu 当设置完时钟分频以后,uboot就会运行cpu_init_crit汇编函数,这个函数的主要作用就是关闭缓存和mmu.然后调用lowlevel_init函数进行系 ...

  6. UVa第五章STL应用 习题((解题报告))具体!

    例题5--9 数据库 Database UVa 1592 #include<iostream> #include<stdio.h> #include<string.h&g ...

  7. Redis学习笔记--Hash(五)

    Redis的数据是通过key-value的方式存储的,对于value的数据类型有字符串.Hash.list.set.sortedSet在redis命令语句中,语句是忽略大小写的,但是key是不可以忽略 ...

  8. IT从业人员关注哪些问题

    技术人员关注的问题非常多,但常见的至少有以下6种.特此整理,抓住核心问题,解决它. 一个人的精力和时间往往非常有限,能把核心问题都解决到位就是成功. 1.职业规划 大家从读小学开始,就是在为职业规划过 ...

  9. Oracle空间数据库的备份与恢复

    大型GIS系统,存储.管理海量(TB级)空间数据时,数据库备份变的尤其重要.这里随笔说说冷备份的一种方法. 基于ArcSDE.Oracle空间库的冷备份: (1) 在数据入库工作后或者更新变动较大时, ...

  10. struts2注入类

    struts2是能够注入一个对象的,那么一定须要继承ModelDriven的泛型接口. package com.test.action; import com.opensymphony.xwork2. ...