数据更新下载

三种方式使得iOS应用能够在后台进行数据更新和下载
三种方式使得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 *)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();
     }
}

时间: 2024-08-26 10:41:02

数据更新下载的相关文章

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

三种方式使得iOS程序即使在关闭或崩溃的情况下也能够在后台持续进行一些任务,比如更新程序界面快照,下载文件等.这三个方法分别是 Background Fetch,Remote Notification和NSURLSession的backgroundSessionConfiguration Background Fetch 开启 首先在info plist文件中开启UIBackgroundModes的Background fetch.或者手动编辑这个值 <key>UIBackgroundMode

新书:锋利的SQL(第2版)开始发售及代码下载

为提高读者学习效率,特提供代码下载:http://download.csdn.net/detail/zhanghongju/8729369 网购京东:http://item.jd.com/11692900.html 网购当当:http://product.dangdang.com/23702533.html 前言 本书第1版是在四年前出版的,但至今仍在被众多的SQL爱好者追捧,甚至不辞辛劳地逐页扫描,上传至网络进行分享.本书第1版是基于SQL Server 2008编写的.时光荏苒,目前SQL

Add-in Express for Microsoft Office and .net下载及介绍

原文来自http://www.fanganwang.com/product/3250转载请注明出处 Add-in Express .NET是市面上的一款直观的Microsoft? Office extensions规划部署工具,它包含了COM Add-ins, Smart Tags, RTD Servers和 Excel 用户定义函数功能,它完全支持Microsoft? Visual Studio? .NET (2003.2005.2008) ,通过它,您可以在上述开发环境中针对现有的所有Mic

GPS接收器控件TGPS下载及功能介绍

TGPS是一个Delphi控件,包装了GPS接收器的相关接口.TGPS是一个GPS接收器接口,它可以用于所有发送NMEA 0183数据的GPS接收器,同时也可以连接计算机的串行通信端口. TGPS的功能特性包括: 可以获取位置.时间.速度.标题.方位.路标.线路等等(主要取决于GPS接收器提供的数据,不同的GPS接收器接收的数据也可能有一些差异) 包含两个组件:提供卫星位置的图片以及信号强度 自动识别COM端口,波特率等等 TGPS 组件在Delphi 3.0, 4.0, 6.0 和 7.0开发

Android基础入门教程——2.4.6 ListView的数据更新问题

Android基础入门教程--2.4.6 ListView的数据更新问题 标签(空格分隔): Android基础入门教程 本节引言: 我们前面已经学习了ListView的一些基本用法咧,但是细心的你可能发现了,我们的数据 一开始定义好的,都是静态的,但是实际开发中,我们的数据往往都是动态变化的,比如 我增删该了某一列,那么列表显示的数据也应该进行同步的更新,那么本节我们就来探讨 下ListView数据更新的问题,包括全部更新,以及更新其中的一项,那么开始本节内容!~ 1.先写个正常的demo先

大量数据更新导致fgc频繁引起jvm服务暂停。

线上跑的几台服务器突然出现大量fgc,由于在fgc过程的stop the world太久,引起其它应用访问该服务器上的接口大量超时.(发生超时的时间点和fgc时间点一致) 先进行初步的优化. 方案:修改CMSInitiatingOccupancyFraction=85这个调低到60,加快cms gc处理防止concurrent mode failure触发FGC, 减少CMSMaxAbortablePrecleanTime到500以缩短PreClean时间. 修改mn2560m为2048,让ed

下载到99.5卡顿问题定位结论

近日升级包下载过程中发现一例问题:升级包下载到99.5卡顿,然后报无法获取网络资源.本文对该问题的做详细定位和总结. 问题原因:下载过程中断网,由于批量写入,因此下载浮标位置更新了,而实际上有一段数据未写入.此时下载完毕了,而系统计算只有99.5左右(有一段数据丢失).此时服务器上已经无数据可下,而系统由于见到到下载进度未到100%,还在持续刷新,刷新超过2分钟发现进度仍没有增加,因此定为网络资源的问题. 下载过程中如果出现退出下载,重新进入,系统会根据前报的进度进行继续下载,因此造成局部数据重

支持.NET和移动设备的XLS读写控件XLSReadWriteII下载地址及介绍

原文来自龙博方案网http://www.fanganwang.com/product/3085转载请注明出处 读写任何单元值 数字型.字符型.布尔型以及错误型.但是你了解日期和时间型单元吗?在Excel中没有这样的单元.Excel是和Delphi一样的方式来存储日期和时间的,即浮点型.那是什么制造了日期或时间值啦,是格式化. 完全支持公式.你可以使用和Excel一样的函数,也支持对外部工作簿引用的公式,你甚至可以从外部引用读取结果. 与操作Delphi的TStringGrid一样的方式操作单元格

WebGrid Enterprise免费下载

WebGrid.NET Enterprise是一个为ASP.NET平台下WEB开发而设计的高级数据表格控件.WebGrid.NET为复杂的分层次导航交互式企业级信息传输提供了全面而先进的功能,它允许用户拥有更多有效的方法来进行信息处理工作. WebGrid Enterprise 是一款针对 ASP . NET平台而设计的数据网格控件.WebGrid . NET Enterprise能够显示和操作标准数据,允许用户自由地对数据进行操作,使用简单,能有效节约您的开发时间.最新版本WebGrid En