iOS ViewController生命周期

ViewController

ViewController是IOS开发中MVC模式中的C,ViewController是view的controller,ViewController的职责主要包括管理内部各个view的加载显示和卸载,同时负责与其他ViewController的通信和协调。

在IOS中,有两类ViewController,一类是显示内容的,比如UIViewController、UITableViewController等,同时还可以自定义继承自UIViewController的ViewController;另一类是ViewController容器,UINavigationViewController和UITabBarController等,UINavigationController是以Stack的形式来存储和管理ViewController,UITabBarController是以Array的形式来管理ViewController。

 

View的加载

可以看到,在Controller中创建View有2种方法,一种是使用Storyboard等可视化工具,另一种是通过代码创建。可视化创建在工程中很少用到,因为它满足不了开发者如饥似渴的需求--。

 

 

IB或Storyboard创建view

通过IB或Storyboard创建view,在Controller中创建view后,会在Controller中对view进行一些操作,会出现如下代码:

@interface MyViewController()
@property (nonatomic) IBOutlet id myButton;
@property (nonatomic) IBOutlet id myTextField;
 
- (IBAction)myAction:(id)sender;
@end

 

这里用IBOutlet标记了一个UIButton和一个UITextField,用IBAction来标记UIButton的响应事件,IBOutlet和IBAction都是一个整形常量,用来标记控件,通过一张图能比较清晰的看清他们之间的关系:

上图中,MyViewController是继承自UIViewController的一个自定义ViewController,它包含两个View,一个是UIButton,一个是UITextField,从箭头的指向性上就可以比较好的理解IBOutlet和IBAction了。IBOutlet是告诉Interface Builder,此实例变量被连接到nib文件中的view对象,IBOutlet本身不做任何操作,只是一个标记作用。IBAction同样是个标记关键字,它只能标记方法,它告诉IB用IBAction标记的方法可以被某个控件触发。

代码创建界面文件

1.创建新的Empty Application Project

2.新建ViewController的类,添加loadView方法,及viewDidLoad等方法

//
//  XYZViewController.m
//  ViewLifeCycle
//
//  Created by Norcy on 14-7-28.
//  Copyright (c) 2014年 QQLive. All rights reserved.
//

#import "XYZViewController.h"

@interface XYZViewController ()

@end

@implementation XYZViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)loadView
{
    UIView *contentView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
    
    contentView.backgroundColor = [UIColor blueColor];
    
    self.view = contentView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    NSLog(@"View Did Load");
}

- (void)viewWillAppear:(BOOL)animated
{
    NSLog(@"View Will Appear");
}

- (void)viewDidAppear:(BOOL)animated
{
    NSLog(@"View Did Appear");
}

- (void)viewWillDisappear:(BOOL)animated
{
    NSLog(@"View Will Disappear");
}

- (void)viewDidDisappear:(BOOL)animated
{
    NSLog(@"View Did Disappear");
}
@end

关于loadView方法的重写,官方文档中有一个明显的注释,原文如下:

Note: When overriding the loadView method to create your views programmatically, you should not call super. Doing so initiates the default view-loading behavior and usually just wastes CPU cycles. Your own implementation of the loadView method should do all the work that is needed to create a root view and subviews for your view controller.

意思是当通过代码方式去创建你自己的view时,在loadView方法中不应该调用super,如果调用[super loadView]会影响CPU性能。

 

3.在AppDelegate.m中的application:didFinishLaunchingWithOptions:中注册ViewController

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    XYZViewController *viewController = [[XYZViewController alloc]initWithNibName:nil bundle:nil];
    self.window.rootViewController = viewController;
    [self.window makeKeyAndVisible];
    return YES;
}

虽然我们可以在AppDelegate.m中的application:didFinishLaunchingWithOptions:中设置window的代码后面添加view,但是在一般的工程中,我们不会在委托类中管理我们的View。 而是利用委托类中的UIWindow去添加UIViewController,再在ViewController类中去管理View。

 

附,创建带NavigationController的代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.backgroundColor = [UIColor whiteColor];
    /*设置Navigation controller*/
    XYZFirstViewController *viewController = [[XYZFirstViewController alloc] initWithNibName:nil bundle:nil];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
    [nav setNavigationBarHidden:YES animated:NO];
    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    [viewController release];
    [nav release];
    return YES;
}

ViewController生命周期

alloc -> initWithNibName -> loadView -> viewDidLoad -> viewWillAppear -> viewDidAppear -> viewWillDisappear -> viewDidDisappear -> dealloc

(init—>loadView—>viewDidLoad—>viewWillApper—>viewDidApper—>viewWillDisapper—>viewDidDisapper—>viewWillUnload->viewDidUnload—>dealloc)

注意viewWillUnload和viewDidUnload已经在ios6被废弃了,因为Clearing references to views is no longer necessary。

注意1.没有viewWillLoad。

注意2.viewDidLoad和viewDidUnload并不是成对的。

 

启动程序

2014-07-28 17:43:36.124 ViewLifeCycle[4007:a0b] View Did Load
2014-07-28 17:43:36.125 ViewLifeCycle[4007:a0b] View Will Appear
2014-07-28 17:43:36.128 ViewLifeCycle[4007:a0b] View Did Appear

按下Home键,并没有任何记录

双击Home键,删除该程序
2014-07-28 17:43:51.327 ViewLifeCycle[4007:a0b] View Will Disappear
2014-07-28 17:43:51.327 ViewLifeCycle[4007:a0b] View Did Disappear

 

为什么按下Home键之后没有调用viewWillDisappear和viewDidDisappear呢?

因为在ios4后引入了后台的概念,当按下Home键之后,程序被挂起了,但是该View依然是原来的View,并不是新的。所以只有内存不够的时候或程序被终止的时候,才会调用viewWillDisappear和viewDidDisappear。

 

View的卸载

 

从图中可以看到,当受到内存警告时,会调用didReceiveMemoeryWarning方法,那么此时系统默认操作会检查当前视图控制器的view是否还在使用,如果没在使用且控制器实现了loadView方法,ViewController会将view release并将其指向为nil。

 

小结一下:

view的nib文件为nil时,手工创建视图界面时调用loadView;当view的nib文件存在的时候,初始化工作在viewDidLoad中实现。

loadView时view还没有生成,viewDidLoad时,view已经生成了。loadView方法用来创建一个新的view。loadView只会被调用一次,而viewDidLoad可能会被调用多次(View可能会被多次加载),当view被添加到其他view中之前,会调用viewWillAppear,之后会调用viewDidAppear。当view从其他view中移除之前,调用viewWillDisAppear,移除之后会调用viewDidDisappear。

注意,不要在loadView中调用父类方法[super loadView],因为这会影响CPU性能。

注意2,切换前后台不会调用viewWillAppear

参考文章

IOS学习笔记——ViewController生命周期详解

IOS开发之界面生命周期(view lifecycle)

iOS ViewController生命周期

IOS学习笔记37——ViewController生命周期详解

 

posted @ 2016-03-22 11:50  黍离麦秀  阅读(284)  评论(0)    收藏  举报