16.0. Introduction(Multitasking)
多任务允许后台运行,意思是应用程序可以继续工作——跑任务,创建新线程,监听通知,事件处理——不过,就没法展示任何界面信息了,也没法与用户交互了。
当用户按下home键,在以前的版本中iPhone和iPad将停止应用程序的运行,而现在应用程序将进入后台。
当应用进入后台或回到前台,系统会发送不同的消息,它希望你的程序代理能处理这些消息,比如进入后台代理将收到applicationDidEnter Background:消息,回到前台将收到applicationWillEnterForeground:消息。
此外,iOS还发送其他消息给应用,当进入后台时发送UIApplicationDidEnterBackgroundNotification,回到前台时发送UIApplicationWillEnterForegroundNotification.如果需要处理这些消息,需要先到通知中心注册。
16.1. Detecting the Availability of Multitasking
检查是否支持多任务
-(void)testMultitaskingSupported
{
if ([selfisMultitaskingSupported]){
NSLog(@"Multitasking is supported.");
} else {
NSLog(@"Multitasking is not supported.");
}
}
- (BOOL) isMultitaskingSupported{
BOOL result = NO;
if ([[UIDevicecurrentDevice]
respondsToSelector:@selector(isMultitaskingSupported)]){
result = [[UIDevicecurrentDevice] isMultitaskingSupported];
}
return result;
}
打印:
2014-07-09 16:28:51.288 cookbook7_12[2767:907] Multitasking is supported.
16.2. Completing a Long-Running Task in the Background
进入后台后还想再执行一段时间
当应用进入后台后,主线程挂起,detachNewThreadSelec tor:toTarget:withObject:创建的子线程也挂起,如果你希望在进入后台后能再执行一会儿时间把还没完成的事做完,你必须调用beginBackgroundTaskWithExpirationHandler:方法给iOS多要点时间。backgroundTimeRemaining属性将会告诉你,你还有多长时间,如果你在这个时间内没结束,那个iOS将强制把你的应用终止掉。
beginBackgroundTaskWithExpirationHandler:方法必须有对应的endBackgroundTask:方法的调用,也就是说你应该告诉iOS你的工作结束了,这样应用就会进入后台,所有线程挂起。
#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
#import "AppDelegate.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSLog(@"%s",__FUNCTION__);
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
NSLog(@"%s",__FUNCTION__);
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
NSLog(@"%s",__FUNCTION__);
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
if ([selfisMultitaskingSupported] == NO){
return;
}
self.myTimer =
[NSTimerscheduledTimerWithTimeInterval:1.0f
target:self
selector:@selector(timerMethod:)
userInfo:nil
repeats:YES];
self.backgroundTaskIdentifier =
[application beginBackgroundTaskWithExpirationHandler:^(void) {
[selfendBackgroundTask];
}];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
NSLog(@"%s",__FUNCTION__);
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
if (self.backgroundTaskIdentifier !=UIBackgroundTaskInvalid){
[selfendBackgroundTask];
}
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
NSLog(@"%s",__FUNCTION__);
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
NSLog(@"%s",__FUNCTION__);
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
- (BOOL) isMultitaskingSupported{
NSLog(@"%s",__FUNCTION__);
BOOL result = NO;
if ([[UIDevicecurrentDevice]
respondsToSelector:@selector(isMultitaskingSupported)]){
result = [[UIDevicecurrentDevice] isMultitaskingSupported];
}
return result;
}
- (void) timerMethod:(NSTimer *)paramSender{
NSLog(@"%s",__FUNCTION__);
NSTimeInterval backgroundTimeRemaining =[[UIApplicationsharedApplication] backgroundTimeRemaining];
if (backgroundTimeRemaining == DBL_MAX){
NSLog(@"Background Time Remaining = Undetermined");
} else {
NSLog(@"Background Time Remaining = %.02f Seconds",backgroundTimeRemaining);
}
}
- (void) endBackgroundTask{
NSLog(@"%s",__FUNCTION__);
dispatch_queue_t mainQueue =dispatch_get_main_queue();
__weak AppDelegate *weakSelf =