zoukankan      html  css  js  c++  java
  • UIViewController的生命周期

    ViewController生命周期

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

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

    注意1.没有viewWillLoad。

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

    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。和Android中Activity一样,IOS开发中,ViewController也有自己的生命周期(Lifecycle)。

    View的加载过程,如下图:

    从图中可以看到,在view加载过程中首先会调用loadView方法,在这个方法中主要完成一些关键view的初始化工作,比如UINavigationViewController和UITabBarController等容器类的ViewController;接下来就是加载view,加载成功后,会接着调用viewDidLoad方法,这里要记住的一点是,在loadView之前,是没有view的,也就是说,在这之前,view还没有被初始化。完成viewDidLoad方法后,ViewController里面就成功的加载view了,如上图右下角所示。

    在Controller中创建view有两种方式,一种是通过代码创建、一种是通过Storyboard或Interface Builder来创建,后者可以比较直观的配置view的外观和属性,Storyboard配合IOS6后推出的AutoLayout,应该是Apple之后主推的一种UI定制解决方案,通过IB或Storyboard创建view,在Controller中创建view后,会在Controller中对view进行一些操作,会出现如下代码:

    视图的加载过程

    AppDelegate.m

    RootViewController *rootViewController = [[RooViewController alloc] init]; // 1

    self.window.rootViewController = rootViewController; // 9

    [rootViewController release];

    -(id)init

    {

      self = [super init]; // 2     里面用到了一个指定初始化方法指定到下面

      if(self){ // 5

       //NSLog(@"%@",self.view); //在创建视图控制器时,不要在视图控制器的初始化方法中做view相关的事情,一般在init方法中初始化一些数据,模型

      }

      return self; // 6

    }

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

    {

      self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; // 3

      if (self) {

        // Custom initialization

      }

      return self; // 4

    }

    一旦覆盖loadView,一定要创建一个视图给视图控制器,可以调用父类的loadview或者自定义一个view,否则的话我们视图的创建是失败的,有可能会引发循环调用的问题

    - (void)loadView // 7

    {

      //第一种方式:调用父类的loadview

      [super loadview];

      //第二种方式:自定义

      UIView *view = [[UIView alloc] initWIthFrame:[[UIScreen mainScreen] appllicationFrame]];

      view.backgroundColor = [UIcolor redColor];

      self.view = view;

      [view release];

          // add subview

    }

    - (void)viewDidLoad // 8

    {

        [super viewDidLoad]; 

      // 1.view -> nil    2.getter method

      // NSLog(@"%@",self.view);

      // 访问网络

    }

    // 视图的出现与消失

    -(void)viewWillAppear:(BOOL)animated

    {

        [super viewWillAppear:(BOOL)animated];

    }

    -(void)viewDidAppear:(BOOL)animated{

        [super viewDidAppear:(BOOL)animated];

    }

    // 视图的卸载(6.0之前)

     

    从图中可以看到,当系统发出内存警告时,会调用didReceiveMemoeryWarning方法,如果当前有能被释放的view,系统会调用viewWillUnload方法来释放view,完成后调用viewDidUnload方法,至此,view就被卸载了。此时原本指向view的变量要被置为nil,具体操作是在viewDidUnload方法中调用self.myButton = nil;

    SecondViewController.h

    @interface SecondViewController:UIViewController

    @property (nonatomic,retain) UIView *subView;

    @end

    SecondViewController.m

    - (void) loadView

    {

      UIView *baseView = [[UIView alloc]initWIthFrame:[[UIScreen mainScreen] appllicationFrame]]; // 1

      baseView.backgroundColor = [UIColor yellowColor];

      self.view = baseView;

      [baseView release];

         // 全局的不要在下面release,他还要给其他人用

      _subView = [[UIView alloc]  initWithFreame:CGRect(60,100,200,200)]; // 1

      _subView.backgroundColor = [UIColor redColor];

      [self.view addSubview:_subView];  // 2

      // 局部变量出了这个方法就没了,意义在于给self.view

      UIView *otherView = [[UIView alloc]initWIthFrame:CGRect(110,350,100,100)]; // 1

      otherView.backgroundColor = [UIColor yellowColor];

      [self.view addSubview:otherView];  // 2

      [otherView release]; // 1

    }

    - (void) viewWillUnload    // 5.0~6.0   这里的view实际上指的就是baseView

    {

      [super viewWillUnload];

    }//视图控制器的视图将要卸载(这行过后视图控制器的view为nil)

    - (void) viewDidUnload // 卸载时,self.view为nil会release一次subView,之后调用self.subView = nil再释放一次。

    {

      [super viewDidUnload];

      // 系统自己判断了,然后释放了self.view -> nil  自己会release,会把它所加的对象都release一遍(otherView也会死掉) //1

      self.subView = nil; // 0

      // NSLog(@"%@",self.view); 不能这样做,因为self.view -> nil    getter方法   会引发[self loadView];

    } // 视图控制器已经卸载,需要卸载掉其他的子视图(强引用)

    - (void)didReceiveMemoryWarning // 6.0之后用这个

    {

      [super didReceiveMemoryWarning];

          // 拿到应用程序的窗口

      // [UIApplication sharedApplication].keyWindow; 或 self.view.window   (window指AppDelegate里面创建的window,只有一个window)

      // NSLog(@"self.view.window : %@",self.view.window); 如果出现内存警告,则view已经deal,所以不能打印这句话

      if ([self.view window] == nil)// 当前的视图控制器中的视图不在当前窗口中

      {

        self.subView = nil;

        self.view = nil; // 6.0之前会帮我们写,之后要自己写 

      }   

    }

    - (void) dealloc

    {

      self.subView = nil;

      [super dealloc];

    }

    @property(nonatomic,retain) UIView *view; // The getter first invokes [self loadView] if the view hasn't been set yet. Subclasses must call super if they override the setter or getter.

    如果这个视图view尚未设置或初始化,那么只要第一次调用getter方法就会引发[self loadView]

    - (void)loadView; // This is where subclasses should create their custom view hierarchy if they aren't using a nib. Should never be called directly.

    如果没有用nib来创建的话,他会创建一个自定义的有层次结构的视图。

    1、alloc                                  创建对象,分配空间

    2、init (initWithNibName)        初始化对象,初始化数据

    3、loadView                           当手动创建时,需要覆盖这个方法,如果 从nib载入视图,通常这一步不需要去干涉。除非你没有使用xib文件创建

    4、viewDidLoad                      载入完成,可以进行自定义数据以及动态创建其他控件,加载网络请求的数据

    5、viewWillAppear                  视图将出现在屏幕之前,马上这个视图就会被展现在屏幕上了

    6、viewDidAppear                  视图已在屏幕上渲染完成

    当一个视图被移除屏幕并且销毁的时候的执行顺序,这个顺序差不多和上面的相反

    1、viewWillDisappear             视图将被从屏幕上移除之前执行

    2、viewDidDisappear             视图已经被从屏幕上移除,用户看不到这个视图了

    3、viewUnLoad                    

    4、dealloc                             视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行

    loadView和viewDidLoad的区别就是,loadView时view还没有生成,viewDidLoad时,view已经生成了,loadView只会被调用一次,而viewDidLoad可能会被调用多次(View可能会被多次加载),当view被添加到其他view中之前,会调用viewWillAppear,之后会调用viewDidAppear。当view从其他view中移除之前,调用viewWillDisAppear,移除之后会调用viewDidDisappear。当view不再使用时,受到内存警告时,ViewController会将view释放并将其指向为nil。

  • 相关阅读:
    OC编程之道-创建对象之工厂方法
    OC编程之道-创建对象之单例模式
    OC编程之道-创建对象之原型模式
    OC编程之道-创建对象之生成器模式
    effective OC2.0 52阅读笔记(七 系统框架)
    effective OC2.0 52阅读笔记(六 块)+ Objective-C高级编程 (二 Blocks)
    effective OC2.0 52阅读笔记(五 内存管理)
    effective OC2.0 52阅读笔记(四 协议与分类)
    安装Sublime Text 3插件的方法
    cocos2d-x学习笔记
  • 原文地址:https://www.cnblogs.com/pjl111/p/4263044.html
Copyright © 2011-2022 走看看