一、视图控制器
UIViewController采用懒加载的方式,也就是说第一次访问到view
属性时才会加载或创建它。由于视图由视图控制器管理,所以讨论视图的加载方式时,主要讨论视图控制器的加载方式。
-
通过Storyboard加载:这是苹果推荐的方式。
通过这种方式创建
UIViewController
对象的话,首先生成UIStoryboard
类型的对象,然后调用这个对象的instantiateViewControllerWithIdentifier:
方法 -
通过Nib文件加载:
Nib文件其实就是xib文件,Storyboard相当于是聚合了多个nib文件,并且添加了对不同的
UIViewController
之间的segue和relationship的管理。但总的实现原理非常类似通过这种方式加载视图,需要调用
UIViewController
类的initWithNibName:bundle:
方法 -
通过loadview方法加载:
这就是通过代码加载。这需要我们在
loadView
方法中,通过编程创建自己的视图层次,并且把把根视图赋值给UIViewController
的view
属性。
二、生命周期
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在最底层;