一、用途和相关概念
iOS中显示ViewController的方式有两种push和modal,modal也叫模态,模态显示VC是iOS的重要特性之一,其主要用于有以下场景:

- 收集用户输入信息
- 临时呈现一些内容
- 临时改变工作模式
- 相应设备方向变化(用于针对不同方向分别是想两个ViewController的情况)
- 显示一个新的view层级

这些场景都会暂时中断APP的正常执行流程,主要作用是收集信息以及显示一些重要的提示等。

presenting view controller & presented view controller
当VCA模态的弹出了VCB,那么VCA就是presenting view controller,VCB就是presented view controller,具体在代码中体现如下:

[VCA presentViewController:VCB animated:YES completion:nil];

container view controller
container view controller 指的是VC的容器类,通过container view controller,我们可以很方便的管理子VC,实现VC之间的跳转等,iOS中container view controller包括 UINavigationController, UISplitViewController, 以及 UIPageViewController.

二、ModalPresentationStyle & Presentation Context

ModalPresentationStyle
presented VC 的modalPresentationStyle属性决定了此次presentation的行为方式及UIKit寻找presentation context的方法,iOS提供了以下几种常用的presentation style:

UIModalPresentationFullScreen

UIKit默认的presentation style。 使用这种模式时,presented VC的宽高与屏幕相同,并且UIKit会直接使用rootViewController做为presentation context,在此次presentation完成之后,UIKit会将presentation context及其子VC都移出UI栈,这时候观察VC的层级关系,会发现UIWindow下只有presented VC.

UIModalPresentationPageSheet

在常规型设备(大屏手机,例如plus系列以及iPad系列)的水平方向,presented VC的高为当前屏幕的高度,宽为该设备竖直方向屏幕的宽度,其余部分用透明背景做填充。对于紧凑型设备(小屏手机)的水平方向及所有设备的竖直方向,其显示效果与UIModalPresentationFullScreen相同。

UIModalPresentationFormSheet

在常规型设备的水平方向,presented VC的宽高均小于屏幕尺寸,其余部分用透明背景填充。对于紧凑型设备的水平方向及所有设备的竖直方向,其显示效果与UIModalPresentationFullScreen相同

UIModalPresentationCurrentContext

使用这种方式present VC时,presented VC的宽高取决于presentation context的宽高,并且UIKit会寻找属性definesPresentationContext为YES的VC作为presentation context,具体的寻找方式会在下文中给出 。当此次presentation完成之后,presentation context及其子VC都将被暂时移出当前的UI栈。

UIModalPresentationCustom

自定义模式,需要实现UIViewControllerTransitioningDelegate的相关方法,并将presented VC的transitioningDelegate 设置为实现了UIViewControllerTransitioningDelegate协议的对象。

UIModalPresentationOverFullScreen

与UIModalPresentationFullScreen的唯一区别在于,UIWindow下除了presented VC,还有其他正常的VC层级关系。也就是说该模式下,UIKit以rootViewController为presentation context,但presentation完成之后不会讲rootViewController移出当前的UI栈。

UIModalPresentationOverCurrentContext

寻找presentation context的方式与UIModalPresentationCurrentContext相同,所不同的是presentation完成之后,不会将context及其子VC移出当前UI栈。但是,这种方式只适用于transition style为UIModalTransitionStyleCoverVertical的情况(UIKit默认就是这种transition style)。其他transition style下使用这种方式将会触发异常。

UIModalPresentationBlurOverFullScreen

presentation完成之后,如果presented VC的背景有透明部分,会看到presented VC下面的VC会变得模糊,其他与UIModalPresentationOverFullScreen模式没有区别。

present VC是通过 UIViewController的presentViewController: animated:completion:
函数实现的,在探讨他们之间的层级关系之前,我们首先要理解一个概念,就是presentation context。
- ### presentation context
presentation context是指为本次present提供上下文环境的类,需要指出的是,presenting VC通常并不是presentation context,Apple官方文档对于presentation context的选择是这样介绍的:

When you present a view controller, UIKit looks for a view controller that provides a suitable context for the presentation. In many cases, UIKit chooses the nearest container view controller but it might also choose the window’s root view controller. In some cases, you can also tell UIKit which view controller defines the presentation context and should handle the presentation.

从上面的介绍可以看出,当我们需要present VC的时候,除非我们指定了context,否则UIKit会优先选择presenting VC所属的容器类做为presentation context,如果没有容器类,那么会选择rootViewController。但是,UIKit搜索context的方式还与presented VC的modalPresentationStyle属性有关,当modalPresentationStyle为UIModalPresentationFullScreen、UIModalPresentationOverFullScreen等模式时,UIKit会直接选择rootViewController做为context。当modalPresentationStyle为UIModalPresentationOverCurrentContext、UIModalPresentationCurrentContext模式时,UIKit搜索context的方式如下:

UIModalPresentationOverCurrentContext、UIModalPresentationCurrentContext模式下,一个VC能否成为presentation context 是由VC的definesPresentationContext属性决定的,这是一个BOOL值,默认UIViewController的definesPresentationContext属性值是NO,而 container view controller的definesPresentationContext默认值是YES,这也是上文中,UIKit总是将container view controller做为presentation context的原因。如果我们想指定presenting VC做为context,只需要在presenting VC的viewDidLoad方法里添加如下代码即可:

self.definesPresentationContext = YES

UIKit搜索presentation context的顺序为:
1. presenting VC
2. presenting VC 的父 VC
3. presenting VC 所属的 container VC
4. rootViewController

还有另外一种特殊情况,当我们在一个presented VC上再present一个VC时,UIKit会直接将这个presented VC做为presentation context。

三、presenting VC 与presented VC 之间的层级关系
在iOS 中,presented VC 总是与 presentation context 处于同一层级,而与presenting VC所在的层级无关,且同一个presentation context同时只能有一个presented VC。

下面我们通过代码来验证这个结论。首先新建一个APP,各VC之间的层级关系如

在SecondContentVC中present FirstPresentVC,代码如下:

FirstPresentVC *vc = [[FirstPresentVC alloc] init];
vc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
[self presentViewController:vc animated:YES completion:nil];

为了更好的观察各VC的层级关系,我们将presented VC 的modalPresentationStyle属性设置为UIModalPresentationOverCurrentContext,这。然后我们再看各VC之间的层级关系:

可以看到FirstPresentVC 与 SecondContentVC的navigationViewController处在同一层级,说明这时的presentation context是navigationViewController。下面我们在FirstContentVC的viewDidLoad方法里添加如下代码:

self.definesPresentationContext = YES;

弹出FirstPresentVC后再看VC之间的层级关系:

可以看到,FirstPresentVC 与 FirstContentVC 处在同一层级,说明此时的 presentation context 为 FirstContentVC.

下面我们将SecondContentVC的definesPresentationContext属性设为YES,然后观察弹出FirstPresentVC之后的层级关系:

可以看到,此时的presentation context为SecondContentVC。这个实验也验证了UIKit 搜索presentation context的顺序。

四、ModalTransitionStyle
modalTransitionStyle可以设置presentation的转场动画,官方提供了几种不同的转场动画,默认是UIModalTransitionStyleCoverVertical。如果想要使用别的style,只需要设置presented VC的modalTransitionStyle属性即可。其余三种包括UIModalTransitionStyleFlipHorizontal、UIModalTransitionStyleCrossDissolve、UIModalTransitionStylePartialCurl.具体每种style的表现形式参考Demo.

tianweitao」原创文章,
原文链接:https://blog.csdn.net/tianweitao/article/details/80314598

详解iOS的presentViewController(转)的更多相关文章

  1. 深拷贝与浅拷贝(mutableCopy与Copy)详解 iOS

    深拷贝与浅拷贝(mutableCopy与Copy)详解 iOS ios中并不是所有的对象都支持copy,mutableCopy,遵守NSCopying 协议的类可以发送copy消息,遵守NSMutab ...

  2. 详解iOS开发之自定义View

    iOS开发之自定义View是本文要将介绍的内容,iOS SDK中的View是UIView,我们可以很方便的自定义一个View.创建一个 Window-based Application程序,在其中添加 ...

  3. 【转】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程

    http://blog.csdn.net/xiaominghimi/article/details/6937097 //——2012-12-11日更新   获取"产品付费数量等于0这个问题& ...

  4. 【iOS开发必收藏】详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程!【2012-12-11日更新获取”产品付费数量等于0的问题”】

    转的别人的 看到很多童鞋问到,为什么每次都返回数量等于0?? 其实有童鞋已经找到原因了,原因是你在 ItunesConnect 里的 “Contracts, Tax, and Banking”没有完成 ...

  5. 详解iOS应用程序内使用IAP/StoreKit付费、沙盒(SandBox)测试、创建测试账号流程

    Himi  原创, 欢迎转载,转载请在明显处注明! 谢谢. 原文地址:http://blog.csdn.net/xiaominghimi/article/details/6937097 //——201 ...

  6. 详解 IOS 7.1 程序启动原理

    程序都是从Main方法入口的 IOS 也不例外 int main(int argc,char * argv[]) { @autoreleasepool { return UIApplicationMa ...

  7. 详解 iOS 上机题!附个人见解

    庸者的救赎2015-11-20 02:30:23 AFN那个使用的时候不需要弱引用的,因为从你的封装方式来看,那个block并不会被当前视图控制器持有,而是被manager持有了,所以不需要__wea ...

  8. iOS无处不在详解iOS集成第三方登录(SSO授权登录无需密码)

    链接地址:http://www.it165.net/pro/html/201408/18884.html 1.前言 不多说,第三登录无处不在!必备技能,今天以新浪微博为例. 这是上次写的iOS第三方社 ...

  9. iOS中 蓝牙2.0详解/ios蓝牙设备详解 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博 整体布局如下:     程序结构如右图: 每日更新关注:http://weibo.com/hanjunqiang  ...

随机推荐

  1. Mysql中的Date转换

    一.背景 Mysql中有张表,表的一列为Date类型. 1. 插入日期xxx.setCreateTime(new Date())mybatis.insert(xxx) 2. 读取日期用Mybaitis ...

  2. win 10 系统安装后的配置

    win10图片恢复默认照片查看器 1. 搜索栏”放大文本大小“ 调整字体大小 2. 桌面显示 我的电脑: 3. 关闭不必要的动画,ctrl+r,输入:control ,打开控制面板

  3. zk单点部署

    一.环境准备 当前环境:centos7.3一台软件版本:zookeeper-3.5.2部署目录:/usr/local/zookeeper启动端口:2181配置文件:/usr/local/zookeep ...

  4. Spring cloud微服务安全实战-8-1课程总结

    总结 首先讲了api的安全.安全常见的风险.安全措施.然后我们把简单的api演化成一个这种微服务的架构. 首先讲了在网关上可以做哪些安全的措施.然后讲了如何搭建一个安全中心,也就是认证服务器,包括一些 ...

  5. IDEA使用Git出现push to origin/master was rejected错误解决方案

    在IDEA中配置码云的URL,如下图 切换到自己项目所在的目录,右键选择GIT BASH Here 在terminl窗口中依次输入命令: git pull git pull origin master ...

  6. LIST<>泛型集合取得对象的属性值

    using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.We ...

  7. python实践项目七:正则表达式版本的strip()函数

    描述:写一个函数,它接受一个字符串,做的事情和 strip()字符串方法一样.如果只传入了要去除的字符串, 没有其他参数, 那么就从该字符串首尾去除空白字符:否则, 函数第二个参数指定的字符将从该字符 ...

  8. PHP_MySQL高并发加锁事务处理

    1.背景: 现在有这样的需求,插入数据时,判断test表有无username为‘mraz’的数据,无则插入,有则提示“已插入”,目的就是想只插入一条username为‘mraz’的记录. 2.一般程序 ...

  9. LeetCode 22. 括号生成(Generate Parentheses)

    22. 括号生成 22. Generate Parentheses 题目描述 给出 n 代表生成括号的对数,请你写出一个函数,使其能够生成所有可能的并且有效的括号组合. 例如,给出 n = 3,生成结 ...

  10. mysql_select 多表查询

    一.等值连接 原理:将多张单表组成一张逻辑大表   语法: select *  from 表A,表B   where 表A.主键=表B.外键 and 查询条件 select *  from 表A,表B ...