UIViewController生命周期

UIView生命周期、程序的生命周期

Posted by Ted on October 15, 2014

一、视图控制器

UIViewController采用懒加载的方式,也就是说第一次访问到view属性时才会加载或创建它。由于视图由视图控制器管理,所以讨论视图的加载方式时,主要讨论视图控制器的加载方式。

  • 通过Storyboard加载:这是苹果推荐的方式。

    通过这种方式创建UIViewController对象的话,首先生成UIStoryboard类型的对象,然后调用这个对象的instantiateViewControllerWithIdentifier:方法

  • 通过Nib文件加载:

    Nib文件其实就是xib文件,Storyboard相当于是聚合了多个nib文件,并且添加了对不同的UIViewController之间的segue和relationship的管理。但总的实现原理非常类似

    通过这种方式加载视图,需要调用UIViewController类的initWithNibName:bundle:方法

  • 通过loadview方法加载:

    这就是通过代码加载。这需要我们在loadView 方法中,通过编程创建自己的视图层次,并且把把根视图赋值给UIViewControllerview属性。

二、生命周期

0、init

UIViewController-init不要出现创建view的代码。良好的设计,在init里应该只有相关数据的初始化,而且这些数据都是比较关键的数据。init里不要掉self.view,否则会导致viewcontroller创建view。(因为view是lazyinit的)。

1、loadView

loadView方法是用来负责创建UIViewController的view

首先,[super loadView]会先去查找与UIViewController相关联的xib文件,通过加载xib文件来创建UIViewController的view

如果没有找到相关联的xib文件,就会创建一个空白的UIView,然后赋值给UIViewController的view属性

默认不用实现

其他情况什么时候会调用呢?

每次访问UIViewController的view(比如controller.view、self.view)而且view为nil,loadView方法就会被调用。

2、ViewDidLoad

loadView方法执行完之后,就会执行viewDidLoad方法。此时整个视图层次(view hierarchy)已经被放到内存中。

无论是从nib文件加载,还是通过纯代码编写界面,viewDidLoad方法都会执行。我们可以重写这个方法,对通过nib文件加载的view做一些其他的初始化工作。比如可以移除一些视图,修改约束,加载数据等。合创建一些附加的view和控件

3、ViewWillAppear

在视图加载完成,并即将显示在屏幕上时,会调用viewWillAppear方法,在这个方法里,可以改变当前屏幕方向或状态栏的风格等。在这里可以进行一些显示前的处理。比如键盘弹出,一些特殊的过程动画(比如状态条和navigationbar颜色)。

4、viewWillLayoutSubviews

即将开始子视图位置布局

5、ViewDidLayoutSubviews

用于通知视图的位置布局已经完成

6、ViewDidAppear

viewWillAppear方法执行完后,系统会执行viewDidAppear方法。在这个方法中,还可以对视图做一些关于展示效果方面的修改。

7、ViewWillDisAppear

视图即将消失

8、ViewDidDisAppear

视图已经消失

9、ViewWillUnload(已废弃)

当内存过低时,需要释放一些不需要使用的视图时,即将释放时调用;

10、ViewDidUnload(已废弃)

当内存过低,释放一些不需要的视图时调用。

三、UIView生命周期其他点

layoutSubviews的被调用的时机:

  • addSubview会触发layoutSubviews,比如viewA add viewB,第一次添加A和B的layoutSubviews都会被调用,而第二次(viewA已经有了viewB)只调用viewB的
  • view的Frame变化会触发layoutSubviews
  • 滚动一个UIScrollView会触发layoutSubviews
  • 旋转Screen会触发父UIView上的layoutSubviews
  • 改变transform属性时,当然frame也会变
  • 处于key window的UIView才会调用(程序同一时间只有一个window为keyWindow,可以简单理解为显示在最前面的window为keywindow)

Push到下一层的顺序

viewWillDisappear->viewWillAppear->viewDidDisappear->viewDidAppear

四、程序的生命周期

应用程序的状态:

  • Not running未运行:程序没启动。
  • Inactive未激活:程序在前台运行,不过没有接收到事件。在没有事件处理情况下程序通常停留在这个状态。
  • Active激活:程序在前台运行而且接收到了事件。这也是前台的一个正常的模式。
  • Backgroud后台:程序在后台而且能执行代码,大多数程序进入这个状态后会在在这个状态上停留一会。时间到之后会进入挂起状态(Suspended)。有的程序经过特殊的请求后可以长期处于Backgroud状态。
  • Suspended挂起:程序在后台不能执行代码。系统会自动把程序变成这个状态而且不会发出通知。当挂起时,程序还是停留在内存中的,当系统内存低时,系统就把挂起的程序清除掉,为前台程序提供更多的内存。

生命周期:

  • application didFinishLaunchingWithOptions:当应用程序启动时执行,应用程序启动入口,只在应用程序启动时执行一次。若用户直接启动,lauchOptions内无数据,若通过其他方式启动应用,lauchOptions包含对应方式的内容。
  • applicationWillResignActive:在应用程序将要由活动状态切换到非活动状态时候,要执行的委托调用,如 按下 home 按钮,返回主屏幕,或全屏之间切换应用程序等。
  • applicationDidEnterBackground:在应用程序已进入后台程序时,要执行的委托调用。
  • applicationWillEnterForeground:在应用程序将要进入前台时(被激活),要执行的委托调用,刚好与applicationWillResignActive 方法相对应。
  • applicationDidBecomeActive:在应用程序已被激活后,要执行的委托调用,刚好与applicationDidEnterBackground 方法相对应。
  • applicationWillTerminate:在应用程序要完全推出的时候,要执行的委托调用,这个需要要设置UIApplicationExitsOnSuspend的键值。

初次启动:

iOS_didFinishLaunchingWithOptions

iOS_applicationDidBecomeActive

按下home键:

iOS_applicationWillResignActive

iOS_applicationDidEnterBackground

点击程序图标进入:

iOS_applicationWillEnterForeground

iOS_applicationDidBecomeActive

点击通知进入:

applicationWillEnterForeground application:didReceiveRemoteNotification applicationDidBecomeActive

从其他APP切回来

applicationWillEnterForeground application:openURL:sourceApplication applicationDidBecomeActive

五、UIWindow与KeyWindow

1、UIWindow

在iOS App中,UIWindow是最顶层的界面内容,我们使用UIWindow和UIView来呈现界面。UIWindow并不包含任何默认的内容,但是它被当作UIView的容器,用于放置应用中所有的UIView。

从继承关系来看,UIWindow继承自UIView,所以UIWindow除了具有UIView的所有功能之外,还增加了一些特有的属性和方法,而我们最常用的方法,就是在App刚启动时,调用UIWindow的rootViewController(必须指定根控制器) 和 makeKeyAndVisible方法

状态栏和键盘都是特殊的UIWindow。

2、UIWindow的主要作用有:

1.作为UIView的最顶层容器,包含应用显示所有的UIView;

2.传递触摸消息和键盘事件给UIView;

把view添加到uiwindow

3、把view添加到uiwindow上面

(1)直接将控制器的view添加到UIWindow中,并不理会它对应的控制器

[self.window addsubview:vc.view];

(2)设置uiwindow的根控制器,自动将rootviewcontroller的view添加到window中,负责管理rootviewcontroller的生命周期

[self.window.rootviewcontroller=vc];

4、KeyWindow

当前app可以打开的多个window 如系统状态栏其实就是一个window ,程序启动的时候创建的默认的window ,弹出键盘也是一个window ,alterView 弹框也是window 。但是keyWindow只有一个 ,一般情况下就是我们程序启动时设置的默认的window

Normal级别是最低的,StatusBar处于中级,Alert级别最高。而通常我们的程序的界面都是处于Normal这个级别的,系统顶部的状态栏应该是处于StatusBar级别,提醒用户等操作位于Alert级别。根据window显示级别优先原则,级别高的会显示在最上层,级别低的在下面,我们程序正常显示的view在最底层;

六、APP架构

七、整体架构

img