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

    生命周期

    我们建立一个简单的模型来测试生命周期:新建两个ViewController,一个是主视图控制器(main ViewController,以下简称mainVC),一个是副视图控制器(sub ViewController,以下简称subVC),在mainVC里点击一个Button,以modal方式切换至subVC,然后在subVC里点击另一个Button关闭subVC并返回mainVC。我们将这两个控制器的每个状态都打印出来,各个阶段的执行如下:

    case 1. 第一次运行app:

    main loadView

    main viewDidLoad

    main viewWillAppear

    main viewDidAppear

     

    case 2. 在mainVC里点击Button,以modal方式切换至subVC:

    sub loadView

    sub viewDidLoad

    main viewWillDisappear

    sub viewWillAppear

    sub viewDidAppear

    main viewDidDisappear

     

    case 3. 在subVC里点击Button关闭subVC并返回mainVC

    sub viewWillDisappear

    main viewWillAppear

    main viewDidAppear

    sub viewDidDisappear

    sub dealloc

     

    当一个视图控制器被创建,并在屏幕上显示的时候代码的执行顺序:

    step 1:alloc 创建对象,分配空间

    step 2:init (initWithNibName) 初始化对象

    step 3:loadView 从nib载入视图 ,通常这一步不需要去干涉。除非你没有使用xib文件创建视图

    step 4:viewDidLoad 载入完成,可以进行自定义数据以及动态创建其他控件

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

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

     

    当一个视图控制器被移除屏幕并且销毁的时候的执行顺序:

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

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

    step 3:dealloc 视图被销毁

     

    这里需要说一下loadView与viewDidLoad的区别:当loadView时,还没有view;而viewDidLoad时,view已经创建好了。详细的加载循环:

    step 1:程序请求ViewController的view属性

    step 2:如果view在内存中,则直接加载;如果不存在,则调用loadView方法

    step 3:loadView方法执行如下方法:

    • 如果重载了这个方法,则必须创建必要的UIView并且将一个非nil值传给ViewController的view属性。
    • 如果没有重载这个方法,ViewController会默认使用自己的nibName和nibBundle属性尝试从nib文件加载view。如果没有找到nib文件,它尝试寻找一个与ViewController类名匹配的nib文件。
    • 如果没有可用的nib文件,那么它创建一个空的UIView作为它的view。

    最后还要考虑一个重要的情况:内存不足警告。当程序收到内存警告的时候,会调用每一个ViewController的didReceiveMemoryWarning方法,我们需要做出相应,释放程序中暂时不需要的资源;通常都会重写该方法,但记得重写的时候要调用super的该方法。

    iOS3.0 - iOS6.0期间,didReceiveMemoryWarning方法会判断当前ViewController的view是否显示在window上,如果没有显示在window上,则didReceiveMemoryWarning会自动将ViewController的view以及其所有子view全部销毁,然后调用View Controller的viewDidUnload方法。但是从iOS6.0开始,viewDidUnload和viewWillUnload这两个方法已被废除,收到low-memory时系统不会释放view,而只是释放controller的resource。

    一种常见处理内存警告的方式:

    复制代码
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        
        float ver = [[[UIDevice currentDevice] systemVersion] floatValue];
        
        if(ver >= 6.0f)
        {
            if(self.isViewLoaded && !self.view.window)
            {
                self.view = nil; //确保下次重新加载
            }
        }
    }
    复制代码

    上面的代码先取得当前iOS系统的版本号,如果是iOS6.0或以上版本,进一步判断视图是否被装载进内存,并且是否为当前视图,在这两个条件都满足(已经装载进内存&&不是当前视图)时,将self.view设置为nil,这样就能保证再调用该ViewController时,loadView和viewDidLoad被再次调用。

    我们在xcode调试器里模拟内存警告,监控此时切换的状态:

    case 4. 当已切换至subVC,模拟内存警告,并返回mainVC,不处理didReceiveMemoryWarning。

    Received memory warning.

    main didReceiveMemoryWarning

    sub didReceiveMemoryWarning

    sub viewWillDisappear

    main viewWillAppear

    main viewDidAppear

    sub viewDidDisappear

    sub dealloc

     

    case 5. 当已切换至subVC,模拟内存警告,并返回mainVC,处理didReceiveMemoryWarning。

    Received memory warning.

    main didReceiveMemoryWarning

    sub didReceiveMemoryWarning

    main loadView

    main viewDidLoad

    sub viewWillDisappear

    main viewWillAppear

    main viewDidAppear

    sub viewDidDisappear

    sub dealloc

     

    可以很明显的看出,当处理了didReceiveMemoryWarning后,重新执行了非当前视图的loadView和viewDidLoad方法。

     

    init/initWithCoder

    loadView

    viewDidLoad

    viewWillAppear

    viewWillLayoutSubviews
    viewDidLayoutSubviews
    viewDidAppear
    viewWillDisappear
    viewDidDisappear

  • 相关阅读:
    Ceph相关
    Redis学习
    docker mysql
    WebSocket学习与使用
    nginx学习与使用
    python学习小记
    基数计数——HyperLogLog
    Swagger使用小记
    理解Java枚举类型
    Jenkins使用
  • 原文地址:https://www.cnblogs.com/shidaying/p/4146358.html
Copyright © 2011-2022 走看看