程序被送入后台后,向 iOS 借时间,完成长期任务-备
12.2.2. 方案
使用UIApplication的beginBackgroundTaskWithExpirationHandler: 实例方法。在你完成任务后,调用UIApplication的endBackgroundTask:方法。
12.2.3. 讨论
当一个iOS应用被送到后台,它的主线程会被暂停。你用NSThread的detachNewThreadSelector:toTar get:withObject:类方法创建的线程也被挂起了。如果你想在后台完成一个长期任务,就必须调用UIApplication的beginBackgroundTaskWithExpirationHandler:实例方法,来向iOS借点时间。UIApplication的backgroundTimeRemaining属性包含了程序完成他的任务可以使用的秒数。如果在这个期限内,长期任务没有被完成,iOS将终止程序。每个对beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用endBackgroundTask:方法(UIApplication的另一个实例方法)。也就是说,如果你向iOS要更多时间来完成一个任务,你必须告诉iOS你什么时候能完成那个任务,那时,你的程序将iOS 5 Programming Cookbook www.devdiv.com 翻译整理
DevDiv 翻译:kyelup cloudhsu 耐心摩卡 wangli2003j3 xiebaochun dymx101 jimmylianf BeyondVincent 20 DevDiv 校对:laigb kyelup DevDiv 编辑:BeyondVincent 版本 1.0 | 2012 年 07 月 30 日
和其所有被暂停的线程被放入后台。
当你的程序在前台时,UIApplication的backgroundTimeRemaining属性等于DBL_MAX常量,这是double类型可表示的最大值(和这个值相当的integer通常等于-1)。在iOS被要求在程序被完全挂起之前给于更多的执行时间,这个属性指明了在完成任务前程序拥有多少秒。
在程序中你可以多次调用beginBackgroundTaskWithExpirationHandler:方法。要记住的重点是,当iOS为你的程序返回一个token或者任务标识(task identifier)时,你都必须调用endBackgroundTask:方法,在运行的任务结束时,用来标志任务结束。如果你不这么做的话,iOS会终止你的程序。
在后台时,程序不应该执行完全的功能,也不应该处理大量数据。事实上,他们只应该完成一个长期任务。
比如,一个程序正在调用一个web service API,并且还没有从服务器上的那个API接收到响应。在此期间,如果程序被送入后台,它可以请求更多的时间,直到它从服务器收到响应。一旦响应被接收,程序必须保存其状态,并调用UIApplication的endBackgroundTask:实例方法将任务标记为完成。
让我们看一个例子。我将从在应用程序委托中定义一个UIBackgroundTaskIdentifier类型的属性开始。同时,让我们定义一个NSTimer,当程序被送到后台时,我们将用它每隔1秒向控制台窗口输出一条消息:
#import <UIKit/UIKit.h>
@interface Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (nonatomic, strong) NSTimer *myTimer;
@end
接下来我们继续同步属性:
#import "Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate.h" @implementation Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate
@synthesize window = _window;
@synthesize backgroundTaskIdentifier; @synthesize myTimer;
现在,让我们创建定时器,并在程序被送到后台时启动它:
- (BOOL) isMultitaskingSupported{
BOOL result = NO;
if ([[UIDevice currentDevice]
respondsToSelector:@selector(isMultitaskingSupported)]){ result = [[UIDevice currentDevice] isMultitaskingSupported];
}
return result;
}
- (void) timerMethod:(NSTimer *)paramSender{
NSTimeInterval backgroundTimeRemaining =
[[UIApplication sharedApplication] backgroundTimeRemaining];
if (backgroundTimeRemaining == DBL_MAX){ NSLog(@"Background Time Remaining = Undetermined");
} else { iOS 5 Programming Cookbook www.devdiv.com 翻译整理
DevDiv 翻译:kyelup cloudhsu 耐心摩卡 wangli2003j3 xiebaochun dymx101 jimmylianf BeyondVincent 21 DevDiv 校对:laigb kyelup DevDiv 编辑:BeyondVincent 版本 1.0 | 2012 年 07 月 30 日
NSLog(@"Background Time Remaining = %.02f Seconds",
backgroundTimeRemaining);
} }
- (void)applicationDidEnterBackground:(UIApplication *)application{
if ([self isMultitaskingSupported] == NO){
return; }
self.myTimer =
[NSTimer scheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(timerMethod:) userInfo:nil
repeats:YES];
self.backgroundTaskIdentifier =
[application beginBackgroundTaskWithExpirationHandler:^(void) { [self endBackgroundTask];
}]; }
你可以看到,在后台任务的完成处理者(completion handler)中,我们调用了应用程序委托的endBackgroundTask方法。这是一个我们编写的方法,如下:
- (void) endBackgroundTask{
dispatch_queue_t mainQueue = dispatch_get_main_queue();
__weak Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate *weakSelf = self;
dispatch_async(mainQueue, ^(void) {
Completing_a_Long_Running_Task_in_the_BackgroundAppDelegate *strongSelf = weakSelf;
if (strongSelf != nil){
[strongSelf.myTimer invalidate];
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTaskIdentifier];
strongSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid; }
}); }
在长期任务结束后,我们需要做一些事情进行清理:
1. 结束所有的线程和定时器,不管他们是基础定时器还是GCD中创建的。
2.调用UIApplication的endBackgroundTask:方法来结束后台任务。
3.将任务标识设置为UIBackgroundTaskInvalid,标志我们的任务结束。
最后,当我们的应用回到前台,如果我们的后台任务还在执行中,我们需要确保我们在干掉它:
- (void)applicationWillEnterForeground:(UIApplication *)application{
if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){
[self endBackgroundTask]; }
}
在我们的例子中,不论何时程序被送到后台,我们都会要求更多时间以完成一个长期任务(例如,在这里是我们计时器的代码)。在我们的时间里,我们不断的读取UIApplication实例中backgroundTimeRemaining属性的值,将它打印到控制台。在UIApplication的beginBackgroundTask WithExpirationHandler: 实例方法中,在程序的额外时间内完成一个长期任务之前,我们提供的代码将被执行(一版大概在任务过期前5到10秒)。在此,我们只要调用UIApplication的endBackgroundTask:实例方法来结束任务。
程序被送入后台后,向 iOS 借时间,完成长期任务-备的更多相关文章
- iOS后台挂起程序 当程序到后台后,继续完成Long-Running Task 任务
我们知道,到我们程序从前台退到后台(安home)键后,将执行程序的委托方法. // 当应用程序掉到后台时,执行该方法 - (void)applicationDidEnterBackground:(UI ...
- IOS 后台挂起程序 当程序到后台后,继续完成Long-Running Task 任务
我们知道,到我们程序从前台退到后台(安home)键后,将执行程序的委托方法. // 当应用程序掉到后台时,执行该方法 - (void)applicationDidEnterBackground:(UI ...
- iOS程序进入后台后仍运行定时器NSTimer
由于本应用需要在应用进入后台后还要进行定时的检测功能,因此对于我来说怎样让APP在进入后台后 保持运行状态是比较大的需求.然后在iOS系统中是很难实现的,不管是 通过 音频还是 定位系统,我查找了一些 ...
- ios开发-程序压后台后,悄悄的抓取数据~~
我们使用某个app的时候,当我们将程序压到后台之后,我们希望它还能从服务器抓取一些数据,类似微博,微信,qq这些程序压后台 之后,我们依然能看到icon上显示未读数量.但是ios系统是伪多任务操作系统 ...
- ios之申请后台延时执行和做一个假后台的方法(系统进入长时间后台后,再进入前台部分功能不能实现)
转自:http://sis hu ok.com/forum/blogCategory/showByCategory.html?categories_id=138&user_id=10385 ...
- 以&运行在后台的程序,关闭terminal后,相应进进程自动关闭
以&运行在后台的程序,关闭terminal后,相应进进程自动关闭
- 如果你恨一个程序员,忽悠他去做iOS开发
如果你恨一个程序员,忽悠他去做iOS开发.不管他背景是cobel还是 java,送他一本iOS开发的书.这种书最好是国人写的,容易以偏概全一点,相比洋鬼子的书,更容易学到皮毛.这叫舍不得孩子套不着狼, ...
- 程序自启动及后台持续运行的研究(voip和GPS方式)
1,voip方式 1)首先要修改应用的plist配置,添加下面的设置: Application does not run in background: NO Requ ...
- 实现iOS长时间后台的两种方法:Audiosession和VOIP(转)
分类: Iphone2013-01-24 14:03 986人阅读 评论(0) 收藏 举报 我们知道iOS开启后台任务后可以获得最多600秒的执行时间,而一些需要在后台下载或者与服务器保持连接的App ...
随机推荐
- 向PE文件中添加一个Section
背景 之前说过直接向类HelloWorld.exe的可执行文件添加一个MessageBox弹窗, 但有时候, 需要添加的内容太多了, 因为数据与代码一起插入, 以至于可执行文件本身没有足够的空闲空间存 ...
- 【HDOJ】2577 How to Type
DP. /* 2577 */ #include <cstdio> #include <cstring> #include <cstdlib> #define MAX ...
- Remote Desktop Connection Manager 多个远程管理
http://www.microsoft.com/en-us/download/details.aspx?id=21101 Remote Desktop Connection Manager 多个远程 ...
- openstack 手动安装版 功能测试
nova network-create demo-net --bridge br100 --multi-host T --gateway 192.168.3.252 --dns1 202.102.19 ...
- hdu1166敌兵布阵
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- java随机数生成器
一.java.lang.Math.Random 调用这个Math.Random()函数能够返回带正号的double值,取值范围是[0.0,1.0)的左闭右开区间,并在该范围内(近似)均匀分布. 二.j ...
- Java使用poi包读取Excel文档
项目需要解析Excel文档获取数据,就在网上找了一些资料,结合自己这次使用,写下心得: 1.maven项目需加入如下依赖: <dependency> <groupId>org. ...
- Python Cookbook笔记
字符串:s.strip() 删除字符串开始和结尾的空白字符. s.lstrip() 删除左边的,s.rstrip() 删除右边的. 随机数:random.random() 生成0-1之间的数. ...
- ajax:html5上传文件,上传之前可以实现本地预览
本主题主要涉及两个新内容: 1.上传文件(主要使用了FormData) 2.本地预览(主要使用了FileReader) html5的FormData其实就是平时的Form表单,只是html5可以直接新 ...
- [React] React Router: Nested Routes
Since react-router routes are components, creating nested routes is as simple as making one route a ...