代码改变世界

IOS开发之后台处理

2013-06-25 14:50  Mr.Xer  阅读(635)  评论(0编辑  收藏  举报

1 前言
IOS4 之后提供了后台处理,在后台运行应用程序,在一些情形下甚至可以在用户按下Home按钮之后在后台运行。

2 详述
IOS可以在用户按下Home按钮后将应用程序添加到暂停状态。这种暂停执行的状态在概念上类似于将Mac设置为休眠模式。应用程序的所有工作内存都在RAM中,在暂停时它完全不执行。因此,切换回这样的应用程序的速度非常快。系统提供了多种方式,通过UIApplication类向应用程序通知其执行状态的变化,该类针对此用途提供了许多委托方法和通知,我们将介绍如何使用他们。

2.1 应用程序的声明周期
2.1.1 未运行
此状态表明所有应用程序都位于一个刚刚重启的设备上,在设备打开状态下,不论应用程序在何时启动,只有遇到以下情况应用程序才返回未运行状态:

(1)应用程序的Info.plist包含UIApplicationExitsOnSuspend键设置为YES;

(2)应用程序之前被暂停并且系统需要清楚一些内存;

(3)应用程序在运行过程中崩溃。

2.1.2 活动
这是应用程序在屏幕上显示时的正常运行状态。他可以接收用户输入并更新显示。

2.1.3 后台
此状态中,应用程序获得了一定的时间来执行一些代码,但是它无法直接访问屏幕或者获得任何用户输入。在用户按下Home按钮后不久,所有应用程序都会进入状态,他们中的大部分会迅速进入暂停状态。希望在后台运行的应用程序一直处于此状态,直到被在此激活。

2.1.4 暂停
暂停的应用程序被冻结。普通的应用程序处于后台不久会转变为此状态。此应用程序在活动时使用的所有内存将原封不懂的得以保留。如果用户将应用程序切换回活动状态,它将回复到之前的状态。另一方面,如果系统需要为当前活动的应用程序提供更多的内存,任何暂停的应用程序都可能被冻结(并返回到未运行状态),他们的内存将释放用于其他用途。

2.1.5 不活动
应用程序仅在两个其他状态之间的临界过度阶段处于不活动状态。应用程序可以在任意长的时间内处于不活动状态的唯一前提是,用户正在处理系统提示(比如显示的传入呼叫或者SMS提示)或用户锁定了屏幕。这基本时上是一种中间的过度状态。

2.2 状态更改通知
为了管理这些状态之间的更改,UIApplication定义了它的委托可以实现的一些方法。除了委托方法,UIApplication还定义了一个匹配的通知名称集合。这使得除了应用程序委托外的其他对象可以在应用程序状态更改时注册通知。

跟踪应用程序的执行状态和相应的通知名称的委托方法:

委托方法通知名称

//可以在application:didFinishLaunchingWithOptions:添加一些应用程序初始化代码。


application:didFinishLaunchingWithOptions:UIApplicationDidFinishLaunchingNotification

//如果按下home按钮,将调用applicationWillResignActive,不应该在applicationWillResignActive中假设应用程序将要进入后台状态,它只是一种临界状态。最终将恢复到活动状态。


applicationWillResignActive:UIApplicationWillResignActiveNotification

//如果稍后将应用程序切回到前台将调用applicationDidBecomeActive


applicationDidBecomeActive:UIApplicationDidBecomeActiveNotification

//释放所有有可能在以后重新创建的资源,保存所有用户数据,关闭网络连接等。如果在这里花了太长时间(超过5秒),系统将断定应用程序的行为异常并终止它。其应该实现applicationWillEnterForeground:来重新创建在applicationDidEnterBackground:中销毁的内容。


applicationDidEnterBackground:UIApplicationDidEnterBackgroundNotification

applicationWillEnterForeground:UIApplicationWillEnterForegroundNotification

//很少用这个方法,只有在应用程序进入后台,并且系统处于某种原因决定跳过暂停状态并终止应用程序时,才会真正调用它。

applicationWillTerminate:UIApplicationWillTerminateNotification

2.3实例解析
接下来我们建立一个项目,来真正的观察你一下这些方法的调用时间:


ZYAppDelegate.m:


[plain]
// 
//  ZYAppDelegate.m 
//  State Lab 
// 
//  Created by zhangyuc on 13-6-8. 
//  Copyright (c) 2013年 zhangyuc. All rights reserved. 
// 
 
#import "ZYAppDelegate.h" 
 
#import "ZYViewController.h" 
 
@implementation ZYAppDelegate 
 
- (void)dealloc 

    [_window release]; 
    [_viewController release]; 
    [super dealloc]; 

 
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 

    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 
    /** 
     *_cmd:Objective-C提供了一个方便的内置变量,名为_cmd,它始终包含当前方法的选择器。 
     *NSStringFromSelector() :函数返回给制定选择器的NSString表示 
     *二者结合可以提供输出当前方法名称的快捷方式,无需重新键入或者复制黏贴它。 
     */ 
    NSLog(@"%@",NSStringFromSelector(_cmd)); 
    self.viewController = [[[ZYViewController alloc] initWithNibName:@"ZYViewController" bundle:nil] autorelease]; 
    self.window.rootViewController = self.viewController; 
    [self.window makeKeyAndVisible]; 
    return YES; 

 
- (void)applicationWillResignActive:(UIApplication *)application 

    // 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. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 

 
- (void)applicationDidEnterBackground:(UIApplication *)application 

    // 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. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 

 
- (void)applicationWillEnterForeground:(UIApplication *)application 

    // 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. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 

 
- (void)applicationDidBecomeActive:(UIApplication *)application 

    // 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. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 

 
- (void)applicationWillTerminate:(UIApplication *)application 

    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     NSLog(@"%@",NSStringFromSelector(_cmd)); 

 
@end 

//
//  ZYAppDelegate.m
//  State Lab
//
//  Created by zhangyuc on 13-6-8.
//  Copyright (c) 2013年 zhangyuc. All rights reserved.
//

#import "ZYAppDelegate.h"

#import "ZYViewController.h"

@implementation ZYAppDelegate

- (void)dealloc
{
    [_window release];
    [_viewController release];
    [super dealloc];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    /**
     *_cmd:Objective-C提供了一个方便的内置变量,名为_cmd,它始终包含当前方法的选择器。
     *NSStringFromSelector() :函数返回给制定选择器的NSString表示
     *二者结合可以提供输出当前方法名称的快捷方式,无需重新键入或者复制黏贴它。
     */
    NSLog(@"%@",NSStringFromSelector(_cmd));
    self.viewController = [[[ZYViewController alloc] initWithNibName:@"ZYViewController" bundle:nil] autorelease];
    self.window.rootViewController = self.viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application
{
    // 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.
     NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    // 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.
     NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationWillEnterForeground:(UIApplication *)application
{
    // 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.
     NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationDidBecomeActive:(UIApplication *)application
{
    // 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.
     NSLog(@"%@",NSStringFromSelector(_cmd));
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
     NSLog(@"%@",NSStringFromSelector(_cmd));
}

@end
运行结果(控制台):

刚进入程序:


2013-06-08 10:29:17.243 State Lab[1866:c07] application:didFinishLaunchingWithOptions:

2013-06-08 10:29:17.248 State Lab[1866:c07] applicationDidBecomeActive:

点击Home键:
再重新回到项目:
最后一种情况很有趣,先将程序迅速地在此激活,然后变为不活动,最后进入后台。
这些委托方法和通知都直接与某种“运行”状态有关:活动,不活动和后台。每个委托方法仅在一种状态中调用(每个通知也仅在一种状态中出现)。最重要的状态过度是在活动状态与其他状态之间,一些过度(比如从后台到暂停)不会出现任何通知。


2013-06-08 10:29:48.598 State Lab[1866:c07] applicationWillResignActive:

2013-06-08 10:29:48.599 State Lab[1866:c07] applicationDidEnterBackground:


2013-06-08 10:30:11.357 State Lab[1866:c07] applicationWillEnterForeground:

2013-06-08 10:30:11.358 State Lab[1866:c07] applicationDidBecomeActive:

如果手机收到一条SMS消息:

2013-06-08 10:29:48.598 State Lab[1866:c07] applicationWillResignActive:


如果关闭该消息:

2013-06-08 10:29:17.248 State Lab[1866:c07] applicationDidBecomeActive:


如果回复SMS消息:

2013-06-08 10:29:17.248 State Lab[1866:c07] applicationDidBecomeActive:


2013-06-08 10:29:48.598 State Lab[1866:c07] applicationWillResignActive:

2013-06-08 10:29:48.599 State Lab[1866:c07] applicationDidEnterBackground: