UIViewController--长篇大论
Posted cchhers
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UIViewController--长篇大论相关的知识,希望对你有一定的参考价值。
1、首先,需要明确VC存在的意义:VC是一个为UIKitApp管理View图层结构的对象。
2、UIViewController这个类定义了大多数VC常用的基类功能。但是一般很少去直接使用UIViewController这个类,而是自定义一个继承于UIViewController的子类,并且在该子类中添加一些属性和方法以方便更好的管理View图层结构。
3、一个VC主要有一下这些职责:
(1)通常需要响应底层的数据变化,来更新Views中的内容。
(2)响应用户与Views的交互操作。
(3)调整Views的大小,并且管理整个界面中的布局。
(4)与其他的对象进行协调,包括其他的VC对象。
4、一个VC对象与与它所管理的Views是紧密相连的,并且VC是需要参与处理Views图层结构中的事件。具体的说,VC是UIResponder对象,并且被插入到VC的根视图和View的父视图之间的响应链中,该View通常属于另一个VC中。一个事件发生了,但是VC中的Views都没有去处理这个事件,那么这个VC也可以选择处理这个事件,或者选择将这个事件沿着事件响应链传递下去。
5、VC很少被单独使用。通常是使用多个VCs,每个VC都拥有app的用户界面的一部分。例如,一个VC可以显示一个项目表,而另一个VC显示从该表中选择的项。通常,每次只能看到来自一个VC的Views。视图控制器可以present不同的视图控制器来显示新的视图集,或者它可以作为其他视图控制器的内容和动画视图的容器。这里涉及到的内容之一就是addChildViewController等一系列方法。
6、每个app都会至少包含一个继承于UIViewController类的自定义的子类。一般而言,是很多。自定义视图控制器定义了应用程序的整体行为,包括应用程序的外观以及它如何响应用户交互。
7、如果想要很好的自定义一个VC类,需要将下面的条目非常的熟悉,并且利用到编程中。
(1)属性view的管理
每个视图控制器管理着一个视图层次结构,视图的根视图存储在该类的视图属性view中。根视图主要充当视图层次结构的其余部分的容器。根视图的大小和位置由拥有它的对象决定,该对象是父视图控制器或应用程序的window。由窗口拥有的视图控制器是应用程序的根视图控制器,其view的大小刚好能填充window。
VC采用懒加载的方式加载他们的view。第一次访问view属性,或者创建VC的view的时候才会加载view。那么如何指定一个VC中的某个view呢?
使用-loadView这个方法指定视图控制器的视图view。在该方法中,以编程方式创建视图层次结构,并将该层次结构的根视图分配给视图控制器的视图属性view。
(2)处理与View相关的通知
View有四种状态:将要显示、已经显示、将要消失、已经消失。有一个需要注意的是,viewWillAppear等方法描述的是View的可见周期,并不是VC的生命周期。
(3)处理View的旋转
(4)实现VC的视图控制器容器功能
VCa、VCa.va、VCb、VCb.vb
可以将vb直接显示在va上,也可以将vb和va混合在一起展现出来。
(5)内存管理
内存是ios中的关键资源,VC提供在关键时刻减少内存占用的内置支持。VC通过-didReceiveMemoryWarning警告方法提供了一些自动处理低内存条件的方法,该方法释放了不需要的内存。
(6)状态的保存和恢复
如果给视图控制器的“修复恢复标识符”属性赋值,系统会要求视图控制器在应用程序转换到后台时对其进行编码。当保存时,视图控制器保留其视图层次结构中具有恢复标识符的任何视图的状态。视图控制器不会自动保存任何其他状态。如果您正在实现自定义容器视图控制器,则必须自己编码任何子视图控制器。编码的每个子必须具有唯一的恢复标识符。
8、用编码的方式创建一个视图控制器
-initWithNibName:bundle:
-initWithCoder:
说明:
UIViewController的初始化有三种方式,分别是代码初始化、从xib初始化和从storyboard初始化。
其中代码初始化和xib初始化基本相同。
初始化方法涉及到:-init、-initWithCoder、-initWithNibName、-awakeFromNib、-loadView、-viewDidLoad。
(1)如果使用storeboard加载视图时的顺序是:
-initWithCoder
-awakeFromNib
-loadView
-viewDidLoad
从执行结果来看,初始化的时候没有执行initWithNibName
方法,为什么呢?
【1】从Apple的文档我们知道,当我们从Storyboard加载view的时候,他不会调用initWithNibName
,而是调用initWithCoder
这个初始化方法。所以Storyboard加载UIViewController的过程应该是这样的: 调用initWithCoder
初始化,然后调用awakeFromNib
说明ViewController加载结束(注意:这个时候ViewController的各个IBOutlet属性都没有加载完)。然后在调用loadView
,最后调用viewDidLoad
方法。
【2】loadView
是一个比较特殊的方法。当访问ViewController的view时,如果view非nil,那么会直接返回这个view;如果view是nil的,那么 ViewController会调用它的loadView方法来加载并把对象赋值给view。如果我们重载了loadView
并且没有调用父类的loadView
导致view属性为nil,系统就会一直调用loadView
方法,知道程序崩溃。
(2)如果使用代码或者xib加载视图时的顺序是:
-init
-initWithNibName
-loadView
-viewDidLoad
【1】从执行结果来看,初始化时先执行init
,再执行initWithNibName
.代码初始化为什么会执行initWithNibName
方法呢? 原来代码初始化的时候,init
会自动调用initWithNibName
方法,如果nibNameOrNil
参数不为空的时候,会去寻找制定xib加载UIViewController
.如果nibNameOrNil
参数为空的时候会去寻找和这个类名相同的xib加载,如果再找不到的话,执行默认初始化。
【2】这个时候不会调用awakeFromNib
这个方法,因为这个方法只有从nib加载的时候才会调用。
9、管理视图
view
说明:这个view是VC的视图层次结构中的根视图。这个属性默认值是nil。但是如果访问这个属性的时候,该属性当前为nil的话。VC会自动调用-loadView方法并返回这个view。有一件事需要尤其注意,VC对象是这个view对象的唯一拥有者,也就是说view被其对应的VC对象唯一强引用着。但是有一个例外,那就是容器控制器可以将另一个VC对象中的view对象当作子视图一样添加到自己的视图层次结构中。但是在在此之前需要调用自己的-addChildViewController:方法,这样的话就能在这两个控制器之间建立一种父子控制器关系。正如之前所说的,访问这个view属性会让vc对象自动的加载它,因此可以通过-viewLoaded属性来确定这个view是否加载到了内存中。还有一点需要注意的是,view这个属性也会自动的变为nil。当内存警告时或者强引用它的vc对象本身内存被释放的时候。
viewLoaded
说明:这个属性就是上面所说到的可以用来判断当前view有没有在内存中。注意的是,访问这个属性,并不能自动将view加载到内存中。
-loadView
说明:首先这个方法是不能直接调用的。这个方法是给vc对象自己调用的,也就是跟上面所说的一样,当访问view这个属性时,view还是一个nil,这vc对象会自动的调这个方法马上创建一个view对象出来。这个方法系统是怎样实现的呢?实现中会判断这个VC有没有关联的nib文件,如果有关联的话,就会通过nib文件来加载view。如果没有关联nib文件的话,这个方法中就会创建一个简单的UIView对象。那么关于这个方法的重写方面呢?如果是使用IB生成器来创建视图并初始化控制器的话,就不能重写这个方法。如果是手动编码的方式,可以重写这个方法,自定义个view。你可以在这个方法中创建很多的views,让他们形成一个视图图层,但是一定要把视图图层中的根视图赋值给view属性。另外有个注意的,重写这个方法的时候,不要调用super的该方法。之后,在这个view的基础上,如果你还想添加一些其他的东西,可以在-viewDidLoad这个方法中执行。
-viewDidLoad
说明:当view创建并初始化后,加载到内存中以后,系统就会调用这个方法(在-loadView方法中不管这个view是通过nib文件加载的还是通过编码的方法加载的,这个方法都会被调用)。通常都会重写这个方法,对view做一些额外的初始化。
-loadViewIfNeeded
说明:调用这个方法时,如果view还没有加载到内存中,那么会根据故事版文件,或者是根据之前约定好的规则创建并加载view。
疑问:这个方法的使用场景?
viewIfLoaded
说明:如果view已经被加载了,则这个属性返回的就是那个view。如果view还没有被加载好,则这个属性返回的就是nil。
疑问:这个属性的使用场景?
title
说明:一个控制器会被直接放置在nav中或者tabvc中,一般设置vc的标题时,我使用的是对应的navigationItem.title或者tabbarItem.title。其实直接赋值vc的title属性,也就相当于修改了对应的title了。
preferredContentSize
说明:这个属性一般是应用在popover情境下,当然在其他场景也是有使用的。当在popover中显示视图控制器时,更改该属性的值会激活大小变化,但是如果指定宽或者高为0.0的话,则该变化就不会被动画化。
10、呈现视图控制器
modalPresentationStyle
说明:这是一个枚举类型,指定的是当一个视图控制器模态展示出来的时候,使用哪种模态跳转方式。在水平compact环境下,模态视图控制器总是呈现全屏。在水平regular环境下,可以有其他的枚举呈现方式。
疑问:水平compact环境和水平regular环境,分别指的是什么。
modelTransitionStyle
说明:当使用presentViewController:animated:completion:这个方法呈现一个视图控制器的时候,使用怎么的动画呈现在屏幕上,就是用这个属性决定的。当然,在present之前将这个属性值设置好才能起作用。这个属性的默认值是UIModalTransitionStyleCoverVertical。
modalInPopover
说明:这个值默认为NO。当为YES时,当在popover中显示视图控制器的时候,外界的其他界面交互将不会影响到该视图控制器。
-showViewController:sender:
说明:这个方法是iOS8.0之后添加的,作用还没弄清楚。
-showDetailViewController:sender:
说明:这个方法是专门为UISlitViewController存在的一个高级版的-showViewController:sender:。
-presentViewController:animated:completion:
-dismissViewControllerAnimated:completion:
definesPresentationContext
providesPresentationContextTransitionStyle
disablesAutomaticKeyboardDismissal
11、支持自定义转换和呈现
transitioningDelegate
transitionCoordinator
-targetViewControllerForAction:sender:
presentationController
popoverPresentationController
restoresFocusAfterTransition
12、响应视图事件
-viewWillAppear:
-viewDidAppear:
-viewWillDisappear:
-viewDidDisappear:
beingDismissed
beingPresented
movingFromParentViewController
movingToParentViewController
13、扩展视图的安全区域
additionalSafeAreaInsets
-viewSafeAreaInsetsDidChange
14、管理视图的边距
viewRespectsSystemMinimumLayoutMargins
systemMinimumLayoutMargins
-viewLayoutMarginsDidChange
15、配置视图的布局行为
edgesForExtendedLayout
extendedLayoutIncludesOpaqueBars
-viewWillLayoutSubviews
-viewDidLayoutSubviews
-updateViewConstraints
16、配置视图旋转设置
shouldAutorotate
supportedInterfaceOrientations
preferredInterfaceOrientationForPresentation
+attemptRotationToDeviceOrientation
17、适应环境变化
-collapseSecondaryViewController:forSplitViewController:
-separateSecondaryViewControllerForSplitViewController"
18、调整界面风格
preferredUserInterfaceStyle
childViewControllerForUserInterfaceStyle
-setNeedsUserInterfaceAppearanceUpdate
UIUserInterfaceStyle
19、在自定义容器中管理子视图控制器
childViewControllers
-addChildViewController:
-removeFromParentViewController
-transitionFromViewController:toViewController:duration:options:animations:completion:
shouldAutomaticallyForwardAppearanceMethods
-beginAppearanceTransition:animated:
-endAppearanceTransition
-setOverrideTraitCollection:forChildViewController:
-overrideTraitCollectionForChildViewController:
20、响应容器事件
-willMoveToParentViewController;
-didMoveToParentViewController:
21、获取其他相关的视图控制器
presentingViewController
presentedViewController
parentViewController
navigationController
splitViewController
tabBarController
22、处理内存警告
-didReceiveMemoryWarning
23、管理状态的恢复
restorationIdentifier
restorationClass
-encodeRestorableStateWithCoder:
-decodeRestorableStateWithCoder:
-applicationfinishedRestoringState
24、支持应用程序扩展
extensionContext
25、使用3D触摸预览和预览快速操作
-registerForPreviewingWithDelegate:sourceView:
-unregisterForPreviewingWithContext:
previewActionItems
26、与系统手势识别器的协调
preferredScreenEdgesDeferringSystemGestures
childViewControllerForScreenEdgesDeferringSystemGestures
-setNeedsUpdateOfScreenedgesDeferringSystemGestures
27、管理状态栏
childViewControllerForStatusBarHidden
childViewControllerForStatusBarStyle
preferredStatusBarStyle
prefersStatusBarHidden
modalPresentationCapturesStatusBarAppearance
preferredStatusBarUpdateAnimation
-setNeedsStatusBarAppearanceUpdate
28、配置手势
prefersHomeIndicatorAutoHidden
childViewControllerForHomeIndicatorAutoHidden
-setNeedsUpdateOfHomeIndicatorAutoHidden
29、配置导航界面
navigationItem
hidesBottomBarWhenPushed
-setToolbarItems:animated:
toolbarItems
30、配置标签卡
tabBarItem
31、向视图控制器添加编辑行为
editing
-setediting:animated:
editButtonItem
32、访问可用的密钥命令
-addKeyCommand:
-removeKeyCommand:
33、获取Nib文件信息
nibName
nibBundle
34、常量
UIModalPresentationStyle
UIModalTransitionStyle
UIrectEdge
35、通知
UIViewControllerShowDetailTargetdidChangeNotification
以上是关于UIViewController--长篇大论的主要内容,如果未能解决你的问题,请参考以下文章