iOS Container View Controller
一.UIViewController
做iOS开发的经常会和UIViewController打交道,从类名可知UIViewController属于MVC模型中的C(Controller),说的更具体点它是一个视图控制器,管理着一个视图(view)。
UIViewController的view是lazy loading的,当你访问其view属性的时候,view会从xib文件载入或者通过代码创建(覆盖loadView方法,自定义其view hierarchy),并返回,如果要判断一个View Controller的view是否已经被加载需要通过其提供的isViewLoaded方法来判断。
view加载后viewDidLoad会被调用,这里可以进行一些数据的请求或加载,用来更新你的界面。
当view将被加入view
hierarchy中的时候viewWillAppear会被调用,view完成加入的时候viewDidAppear会被调用,同样当view将要从
view hierarchy中移除的时候viewWillDisappear会被调用,完成移除的时候viewDidDisappear会被调用。
当内存紧张的时候,所有的UIViewController对象的didReceiveMemoryWarning会被调用,其默认实现是
如果当前viewController的view的superview是nil的话,则将view释放且viewDidUnload会被调
用,viewDidUnload中你可以进行后继的内存清理工作(主要是界面元素的释放,当再次加载的时候需要重建)。
如果想要展示一个View Controller,一般有如下一种途径
- 设置成Window的rootViewController(iOS 4.0之前UIWindow并没有rootViewController属性,只能通过addSubview的方式添加一个View Controller的view)
- 使用某个已经存在的Container来展示,比如使用UINavigationController来展示某个View Controller
[navigationController pushViewController:vc animated:YES]; - 以模态界面的方式展现出来 presentModalViewController
- 以addSubview的方式将使其view作为另一个View Controller的view的subView
直接使用4种方法是比较危险的,上一级 View Controller并不能对当前View Controller的 生命周期相关的函数进行调用,以及旋转事件的传递等。
二.Hierarchy
我们知道一个View可以将另一个View添加为子View(subview),构成一个View
Hierarchy.当某一个View添加到window的View Hierarchy中时,将被“显示”。每一个View
Controller管理着的其实就是一个View Hierarchy.而View Controller本身可以有Child View
Controller,所以也存在一个 View Controller Hierarchy的概念,当View
Controller收到上层传来的诸如旋转,显示事件的时候,需要传递给它的Child View Controller.
一般情况下,View Hierarchy 和 View Controller Hierarchy需要保持一致性,比如一个View
Controller的view的superView是由其parent view controller管理着

三.Container
一个iOS的app很少只由一个ViewController组成,除非这个app极其简单。
当有多个View Controller的时候,我们就需要对这些View Controller进行管理。
那些负责一个或者多个View Controller的展示并对其视图生命周期进行管理的对象,称之为容器,大部分容器本身也是一个View
Controller,这样的容器可以称之为Container View Controller,也有极少数容器不是View
Controller,比如UIPopoverController,其继承于NSObject。
我们常用的容器有 UINavigationController,UITabbarController等,一般容器有一些共同的特征:
- 提供对Child View Controller进行管理的接口,比如添加Child View Controller,切换Child View Controller的显示,移除Child View Controller 等
- 容器“拥有”所有的Child View Controller
- 容器需要负责 Child View Controller的appearance callback的调用(viewWillAppear,viewDidAppear,viewWillDisaapper,viewDidDisappear),以及旋转事件的传递
- 保证view hierarchy 和 view controller hierarchy 层级关系一致,通过parent view controller将child view controller和容器进行关联
从上面可以看出来,实现一个Container View
Controller并不是一个简单的事情,好在iPhone的界面大小有限,一般情况下一个View
Controller的view都是充满界面或者系统自带容器的,我们无需自己创建额外的容器,但是在iPad中情况就不同了。
四.Custom Container View Controller
在iOS 5之前框架并不支持自定义 Container View Controller, iOS 5开始开放了一些新的接口来支持支持自定义容器
addChildViewController:
removeFromParentViewController
transitionFromViewController:toViewController:duration:options:animations:completion:
willMoveToParentViewController:
didMoveToParentViewController:
其中前两个接口比较重要,可以直接改变View Controller 的 Hierarchy。
有点意外的是,在不做任何额外设置的情况下进行如下操作
[viewController.view addSubview:otherViewController.view]
iOS 5中otherViewController是可以立刻收到viewWillAppear和viewDidAppear的调用。
至于旋转事件的传递以及其他时机viewWillAppear viewDidAppear的调用是需要建立在 [viewController addChildViewController:otherViewController]基础上的。
当我们需要在iOS 4上实现自定义容器,或者有时候我们不想让viewWillAppear这类方法被自动调用,而是想自己来控制,这个时候我们就得需要手动来调用这些方法,而不是由框架去自动调用。 iOS 5中可以很方便的禁用掉自动调用的特性,覆盖automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers返回NO
但是单单覆盖这个方法在iOS5下还是有问题的,当执行下面的语句的时候
[viewController.view addSubview:otherViewController.view]
otherViewController还是是可以立刻收到viewWillAppear和viewDidAppear的调用。
解决这一问题的方法就是在iOS5的时候调用[viewController.view addSubview:otherViewController.view]之前 进行如下操作
[viewController addChildViewController:otherViewController]
总的来说实现兼容iOS 4和iOS 5的容器有不少问题和注意点的
- view加入view层级前后分别调用viewWillAppear和viewDidAppear;容器的 viewWillAppear,viewDidAppear,viewWillDisappear,viewDidDisappear中需要对当前显示的 Child View Controller调用相同的方法,容器需要保证Child View Controller的viewWillAppear调用之前Child View Controller的view已经load了.还有一点就是保证容器的View不会出现bounds为CGRectZero的情况,因为如果此View 包含多个subview,其bounds改变的时候subview会根据自己的autoresizingMask改变frame,但是当bounds变为 0再变为非0的时候,subview的frame就有可能不是你想要的了(比如某个subview的autoresizingMask为 UIViewAutoresizingFlexibleBottomMargin)
- 容器的shouldAutorotateToInterfaceOrientation中需要检测每一个Child View Controller的shouldAutorotateToInterfaceOrientation如果一个不支持,则看做不支持
- 容器的 willRotateToInterfaceOrientation,didRotateFromInterfaceOrientation,willAnimateRotationToInterfaceOrientation 方法中需要将这些事件传递给所有的Child View Controller
- 由于UIViewController的parentViewController属性为只读,且iOS4中没有提供容器支持的接口(iOS 5中容器支持的接口会间接的维护这个属性),所以为了使得childViewController和容器得以关联,我们可以顶一个View Controller的基类,添加一个比如叫做superController的属性用来指定对应的parentViewController
- 由于UIViewController的interfaceOrientation为只读属性,且iOS5中没有提供容器接口,所以 UIViewController的这个interfaceOrientation变的不可信,为了取得当前UIViewController的 orientation我们可以用UIWindow下的rootViewController的interfaceOrientation的值
- 容器的viewDidUnload方法中需要对view未释放的childViewController的view进行释放,且调用其viewDidUnload方法
苹果对UIViewController以及其使用有着非常详细的文档 UIViewController Reference , ViewController Programming Guide。
另一个参考链接:http://geeklu.com/2014/05/custom-container-view-controller/
iOS Container View Controller的更多相关文章
- iOS 容器控制器 (Container View Controller)
iOS 容器控制器 (Container View Controller) 一个控制器包含其他一个或多个控制器,前者为容器控制器 (Container View Controller),后者为子控制器 ...
- 《iOS Human Interface Guidelines》——Container View Controller
容器视图控制器 容器视图控制器管理和展示它的子视图集合--或者子控制器集合--以一种自己定义的方式. 系统定义的容器视图控制器的样例有标签栏视图控制器.导航栏视图控制器和分栏视图控制器(查看Tab B ...
- Container View Controller
有时候,我们的Controler中包含有另一个controler view的view时,可以使用这种方式. https://developer.apple.com/library/ios/featur ...
- IOS Note - View Controller(视图控制器)
Application Delegate(应用程序委托) Application Name: SingleView SingleViewAppDelegate.h #import <UIKit/ ...
- 【IOS笔记】View Controller Basics
View Controller Basics 视图控制器基础 Apps running on iOS–based devices have a limited amount of screen s ...
- View Controller Programming Guid for iOS 笔记
1.View Controller 基础 1.1 View Controller 分类 ViewController分为container view controller 和content view ...
- View Controller 视图管理总结
View controller是iOS中顶层的视图载体和控制器,它需要对view负责,管理view的生命周期,相关处室话以及交互事件,除此以外还需要为view提供合适的数据,以供view使用. Vie ...
- View Controller Programming Guide for iOS---(七)---Resizing the View Controller’s Views
Resizing the View Controller’s Views A view controller owns its own view and manages the view’s cont ...
- View Controller Programming Guide for iOS---(四)---Creating Custom Content View Controllers
Creating Custom Content View Controllers 创建自定义内容视图控制器 Custom content view controllers are the heart ...
随机推荐
- Windows 下 Composer 与 Laravel 4 的安装
1.安装Composer Composer是PHP的依附经管对象之一,官方网站 http://getcomposer.org/ .它支撑多种安装体式格式,对于在win下做开辟的草来说,最便捷的体式格式 ...
- 【转】常用插件和mvn test命令
自定义构建Maven项目,需要包括额外的插件或者配置已存在的插件参数. 1. maven-compiler-plugin 指定JDK版本和编码方式 compiler插件能解决2个问题: 第一: mav ...
- WPF学习笔记 控件篇 属性整理【1】FrameworkElement
最近在做WPF方面的内容,由于好多属性不太了解,经常想当然的设置,经常出现自己未意料的问题,所以感觉得梳理下. ps:先补下常用控件的类结构,免得乱了 .NET Framework 4.5 Using ...
- linux c 分解质因数
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> ...
- hadoop集群默认配置和常用配置【转】
转自http://www.cnblogs.com/ggjucheng/archive/2012/04/17/2454590.html 获取默认配置 配置hadoop,主要是配置core-site.xm ...
- c++中string类的详解
,<时返回-1,==时返回0 string的子串:string substr(int pos = 0,int n = npos) const;//返回pos开始的n个字符组成的字符串strin ...
- C++中的运算符优先级
1 () [] . ->2 ! ~ -(负号) ++ -- &(取变量地址)* (type)(强制类型) sizeof 3 * / % 4 + ...
- SQL Server 数据库最小宕机迁移方案
一.目的 在做SQL Server数据库维护的时候,当上司要求我们把几十G的数据文件搬动到其它服务器,并且要求最小宕机时间的时候,我们有没什么方案可以做到这些要求呢? 在这里我们假设这两台机器并不是在 ...
- Team Homework #3: The feedback of predecessors
此次对学长的采访主要在QQ上进行,感谢陈宇宁学长的热情配合. 采访学长的问题及学长的答复如下: 1. 平均每周花在这门课上的时间 (包括上课/作业/上机) -大约15-20小时吧(学长个人花费时间) ...
- 求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
// test20.cpp : 定义控制台应用程序的入口点. // include "stdafx.h" include include include include inclu ...