多任务(1)
来源:互联网 发布:linux设置硬件时间 编辑:程序博客网 时间:2024/06/16 09:24
介绍:
多任务允许“后台执行”(background execution),意味着程序可以像往常一样工作---运行任务,产生大量的新线程,等候通知并对事件作出反应---但不会在屏幕上显示任何东西或者以任何方式和用户交互。当用户按下设备上的 Home 按钮,这在之前的版本将终止 iPhone 或者 iPad 上的应用程序,现在程序会被送到后台。
当我们的程序转到后台(比如用户按下了 Home 按钮)然后回到前台(当用户再次选择 程序时),系统会发送一些不同的消息,期待被我们指派的应用程序委托对象接收。比如, 当我们的程序被送到后台,应用程序委托将会收到 applicationDidEnterBackground: 方法,当 程序被用户切到前台,应用程序委托将收到 applicationWillEnterForeground:委托消息。
除了这些委托消息,在程序前后台切换时,iOS 也向运行中的程序发送通知。程序转入后台时发送的通知是 UIApplicationDidEnterBackgroundNotification,从后台切回前台发送的通知为 UIApplicationWillEnterForegroundNotification。你可以使用默认通知中心来注册这些通知。
1.检测多任务Identifier可用性
1.1. 问题
你想知道正运行你程序的 iOS 设备是否支持多任务。
1.2. 方案
调用 UIDevice 对象的实例方法 isMultitaskingSupported,如下:
//检测是否支持多任务
- (BOOL)isMultitaskingSupported{
BOOL result = NO;
if ([[UIDevicecurrentDevice]respondsToSelector:@selector(isMultitaskingSupported)]) {
result = [[UIDevicecurrentDevice]isMultitaskingSupported];
}
return result;
}
2.在后台完成一个长期任务(Long-Runing Task)
2.1. 问题
你希望能在程序被送入后台时,向 iOS 借点时间,来完成一个长期任务。
2.2. 方案
使用 UIApplication 的 beginBackgroundTaskWithExpirationHandler: 实例方法。在你完成任务后,调用 UIApplication 的 endBackgroundTask:方法。
当一个 iOS 应用被送到后台,它的主线程会被暂停。你用 NSThread 的 detachNewThreadSelector:toTarget:withObject:类方法创建的线程也被挂起了。如果你想在后 台完成一个长期任务,就必须调用 UIApplication 的 beginBackgroundTaskWithExpirationHandler:实例方法,来向 iOS 借点时间.UIApplication的backgroundTimeRemaining 属性包含了程序完成他的任务可以使用的秒数。如果在这个期限内,长期任务没有被完成,iOS 将终止程序。每个对beginBackgroundTaskWithExpirationHandler:方法的调用,必须要相应的调用 endBackgroundTask:方法(UIApplication 的另一个实例方法)。也就是说,如果你向 iOS 要 更多时间来完成一个任务,你必须告诉 iOS 你什么时候能完成那个任务,那时,你的程序将 和其所有被暂停的线程被放入后台。
当你的程序在前台时,UIApplication 的 backgroundTimeRemaining 属性等于 DBL_MAX 常量,这是 double 类型可表示的最大值(和这个值相当的 integer 通常等于-1)。在 iOS 被 要求在程序被完全挂起之前给于更多的执行时间,这个属性指明了在完成任务前程序拥有多少秒。
在程序中你可以多次调用 beginBackgroundTaskWithExpirationHandler:方法。要记住的重 点是,当 iOS 为你的程序返回一个 token 或者任务标识(task identifier)时,你都必须调用 endBackgroundTask:方法,在运行的任务结束时,用来标志任务结束。如果你不这么做的话,iOS 会终止你的程序。
在后台时,程序不应该执行完全的功能,也不应该处理大量数据。事实上,他们只应该完成一个长期任务。
比如,一个程序正在调用一个 web service API,并且还没有从服务器上的那个 API 接收 到响应。在此期间,如果程序被送入后台,它可以请求更多的时间,直到它从服务器收到响 应。一旦响应被接收,程序必须保存其状态,并调用 UIApplication 的 endBackgroundTask:实例方法将任务标记为完成。
让我们看一个例子。我将从在应用程序委托中定义一个 UIBackgroundTaskIdentifier 类型 的属性开始。同时,让我们定义一个 NSTimer,当程序被送到后台时,我们将用它每隔 1 秒 向控制台窗口输出一条消息:
.h
#import <UIKit/UIKit.h>
@interface AppDelegate :UIResponder <UIApplicationDelegate>
@property (strong,nonatomic) UIWindow *window;
@property (nonatomic ,unsafe_unretained)UIBackgroundTaskIdentifier backgroundTaskIdentifier;
@property (nonatomic ,strong)NSTimer *myTimer;
@end
//.1现在,让我们创建定时器,并在程序被送到后台时启动它:
- (void)timerMethod:(NSTimer *)paramSender{
NSTimeInterval backgroundTimeRemaining = [[UIApplicationsharedApplication]backgroundTimeRemaining];//remaining adj.剩余的,剩下的
if (backgroundTimeRemaining == DBL_MAX) {
NSLog(@"Background Time Remaining = Undetermined");
}else{
NSLog(@"Background Time Remaining = %.02f Seconds", backgroundTimeRemaining);
}
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
self.myTimer = [NSTimerscheduledTimerWithTimeInterval:1.0ftarget:selfselector:@selector(timerMethod:)userInfo:nilrepeats:YES];
self.backgroundTaskIdentifier = [applicationbeginBackgroundTaskWithExpirationHandler:^{
[selfendBackgroundTask];
}];
// expiration /ˌekspɪ'reɪʃ(ə)n/ 截止,告终;呼气,吐气
}
//.2 你可以看到,在后台任务的完成处理者(completion handler)中,我们调用了应用程序委托的 endBackgroundTask 方法。这是一个我们编写的方法,如下:
- (void)endBackgroundTask{
dispatch_queue_t mainQueue =dispatch_get_main_queue();
__weak AppDelegate *weakSelf =self;
dispatch_async(mainQueue, ^{
AppDelegate *strongSelf = weakSelf;
if (strongSelf != nil) {
/*在长期任务结束后,我们需要做一些事情进行清理:
1. 结束所有的线程和定时器,不管他们是基础定时器还是 GCD中创建的。
2.调用 UIApplication 的 endBackgroundTask:方法来结束后台任务。
3.将任务标识设置为 UIBackgroundTaskInvalid,标志我们的任务结束。
*/
[strongSelf.myTimer invalidate];
[[UIApplicationsharedApplication]endBackgroundTask:self.backgroundTaskIdentifier];
strongSelf.backgroundTaskIdentifier =UIBackgroundTaskInvalid;
}
NSLog(@"结束后台");
});
}
//.3 最后,当我们的应用回到前台,如果我们的后台任务还在执行中,我们需要确保我们在干掉它:
- (void)applicationWillEnterForeground:(UIApplication *)application {
if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid) {
[self endBackgroundTask];
}
}
模拟运行时,进入后台一直等待时打印结果:
2014-12-19 11:24:14.283多任务Identifier[2079:332066] Background Time Remaining = 179.01 Seconds
2014-12-19 11:24:15.283多任务Identifier[2079:332066] Background Time Remaining = 178.01 Seconds
2014-12-19 11:24:16.282多任务Identifier[2079:332066] Background Time Remaining = 177.01 Seconds
......2014-12-19 11:27:07.273多任务Identifier[2079:332066] Background Time Remaining = 6.01 Seconds
2014-12-19 11:27:08.274多任务Identifier[2079:332066] Background Time Remaining = 5.01 Seconds
2014-12-19 11:27:08.288多任务Identifier[2079:332066]结束后台
2014-12-19 11:33:39.240多任务Identifier[2194:352062] Background Time Remaining = 179.01 Seconds
2014-12-19 11:33:40.240多任务Identifier[2194:352062] Background Time Remaining = 178.01 Seconds
2014-12-19 11:33:41.240多任务Identifier[2194:352062] Background Time Remaining = 177.01 Seconds
2014-12-19 11:33:42.240多任务Identifier[2194:352062] Background Time Remaining = 176.01 Seconds
2014-12-19 11:33:42.354多任务Identifier[2194:352062]结束后台
2.4 总结
在我们的例子中,不论何时程序被送到后台,我们都会要求更多时间以完成一个长期任务(例如,在这里是我们计时器的代码)。在我们的时间里,我们不断的读取 UIApplication 实例中 backgroundTimeRemaining 属性的值,将它打印到控制台。在 UIApplication 的 beginBackgroundTask WithExpirationHandler: 实例方法中,在程序的额外时间内完成一个长期任务之前,我们提供的代码将被执行(一版大概在任务过期前 5 到 10 秒)。在此,我们只要调用 UIApplication 的 endBackgroundTask:实例方法来结束任务。
当一个程序被送到后台而且它从 iOS 请求了额外执行时间,在执行时间 完成之前,程序可以被用户唤醒并被带回到前台。如果你在程序被送到后台时请求过执行一 个长期任务,那么此时你必须使用 UIApplication 的 BackgroundTask:实例方法结束这个长期任务。
- 多任务(1)
- 多任务--任务管理
- 多任务和多线程(1)
- 1、早期的多任务
- vxworks---多任务(1)
- 多任务
- 多任务
- 多任务
- 多任务
- 多任务
- 多任务
- 任务 1
- 任务1
- 多任务 任务的划分
- Windows多线程多任务设计初步1
- C++多任务编程简明教程 (1)
- C++多任务编程简明教程 (1)
- 第二十章 多任务和多线程(多任务的各种模式1)
- MyEclipse生成WAR包并在Tomcat下部署发布
- 支付宝钱包手势密码破解实战(root过的手机可直接绕过手势密码)
- cocoapods速成手册(1)
- Objective-C 空Block用法
- C++中字节对齐
- 多任务(1)
- 《算法导论》中的逆序数对问题
- 项目从Delphi 7 升级到Delphi2010过程中遇到的有关FormPaint的问题
- 为什么我看不懂你的代码
- apple 应用程序发布流程相关
- assert()函数用法总结
- maven创建spring骨架首次jetty:run找不到表“user_role”
- OC语言之三大特性
- cookie中添加token消除cookie被修改的安全隐患