您的位置:首页 > 其它

PresentModalViewController(模态) 相关问题总结

2015-11-29 13:47 453 查看



一、主要用途

  弹出模态ViewController是IOS变成中很有用的一个技术,UIKit提供的一些专门用于模态显示的ViewController,如UIImagePickerController等。弹出模态ViewController主要使用于一下这几种情形:

  1、收集用户输入信息

  2、临时呈现一些内容

  3、临时改变工作模式

  4、相应设备方向变化(用于针对不同方向分别是想两个ViewController的情况)

  5、显示一个新的view层级

  这几种情形都会暂时中断程序正常的执行流程,主要作用是收集或者显示一些信息。

二、几个概念和常用设置

1、presenting view controller Vs presented view controller

  当我们在view controller A中模态显示view controller B的时候,A就充当presenting view controller(弹出VC),而B就是presented view controller(被弹出VC)。官方文档建议这两者之间通过delegate实现交互,如果使用过UIImagePickerController从系统相册选取照片或者拍照,我们可以发现imagePickerController和弹出它的VC之间就是通过UIImagePickerControllerDelegate实现交互的。因此我们在实际应用用,最好也遵守这个原则,在被弹出的VC中定义delegate,然后在弹出VC中实现该代理,这样就可以比较方便的实现两者之间的交互。

2、Modal Presentation Styles(弹出风格)

  通过设置presenting VC的modalPresentationStyle属性,我们可以设置弹出View Controller时的风格,有以下四种风格,其定义如下:

typedef enum {

UIModalPresentationFullScreen = 0,

UIModalPresentationPageSheet,

UIModalPresentationFormSheet,

UIModalPresentationCurrentContext,

} UIModalPresentationStyle;

  UIModalPresentationFullScreen代表弹出VC时,presented VC充满全屏,如果弹出VC的wantsFullScreenLayout设置为YES的,则会填充到状态栏下边,否则不会填充到状态栏之下。

  UIModalPresentationPageSheet代表弹出是弹出VC时,presented VC的高度和当前屏幕高度相同,宽度和竖屏模式下屏幕宽度相同,剩余未覆盖区域将会变暗并阻止用户点击,这种弹出模式下,竖屏时跟UIModalPresentationFullScreen的效果一样,横屏时候两边则会留下变暗的区域。

  UIModalPresentationFormSheet这种模式下,presented VC的高度和宽度均会小于屏幕尺寸,presented VC居中显示,四周留下变暗区域。

  UIModalPresentationCurrentContext这种模式下,presented VC的弹出方式和presenting VC的父VC的方式相同。

  这四种方式在iPad上面统统有效,但在iPhone和iPod touch上面系统始终已UIModalPresentationFullScreen模式显示presented VC。

3、Modal Transition Style(弹出时的动画风格)

  通过设置设置presenting VC的modalTransitionStyle属性,我们可以设置弹出presented VC时场景切换动画的风格,其定义如下:

typedef enum {

UIModalTransitionStyleCoverVertical = 0,

UIModalTransitionStyleFlipHorizontal,

UIModalTransitionStyleCrossDissolve,

UIModalTransitionStylePartialCurl,

} UIModalTransitionStyle;

  我们可以看到有从底部滑入,水平翻转进入,交叉溶解以及翻页这四种风格可选。这四种风格在不受设备的限制,即不管是iPhone还是iPad都会根据我们指定的风格显示转场效果。

4、Dismiss Modal ViewController(消失弹出的VC)

  消失presented VC,我们可以通过调用以下两个函数中的任何一个来完成

dismissModalViewControllerAnimated: // 将要废弃,不赞成继续使用

dismissViewControllerAnimated:completion:

  谁来调用这消失presented VC的这个方法:正确的做法是“谁污染谁治理”,即presenting VC调用上面的方法来取消presented VC的显示。这样做有一个好处,如果一个VC真不用户做的不同选择可能弹出不同的view controller,当不再需要显示被弹出的view controller的时候,直接调用[self dismissModalViewControllerAnimated]即可使之消失,而不用去关心其具体显示的哪一类view
controller。当然系统在这里做了优化,当我们在presented VC里面调用上面的方法的时候,系统会自动的将这个消息传递到相应的presenting VC中,这样就可以实现不管谁弹出了自己,当不再需要的时候直接将自己消失掉的功能。在应用中具体要采用那种要看具体情况,如果presented VC需要和presenting VC有数据传递的话,建议在presenting VC实现的代理函数中dismiss弹出的view controller。

延伸阅读:

场景切换

多个场景之间切换的样式(Style)总共有5个:

Modal(模态) -- 过渡到另一个场景,以完成一项任务。任务完成后,将关闭该场景,并返回到原来的场景。

Push(压入) -- 创建一个场景链,用户可在其中前后移动。用于导航视图控制器。

Replace(替换,仅适用于iPad) -- 替换当前场景,用于一些iPad特有的视图控制器。

Popover(弹出框,仅适用于iPad) -- 一个带箭头的弹出框。

Custome(自定义) -- 通过编译在场景之间进行自定义过渡。
过渡类型(Transition)是从一个场景切换到另一个场景时播放的动画。有4个选项:

Cover Vertical -- 新场景从下向上移动,逐渐覆盖旧场景。

Flip Horizontal -- 视图水平翻转,以显示背面的新场景。

Cross Dissolve -- 旧场景淡出,新场景淡入。

Partial Curl -- 旧场景像书页一样翻开,显示下面的新场景。

在iPad应用程序中,还会多出一个Presentation属性,它决定了模态视图在屏幕上的显示方式。有4种显示样式:

Form Sheet(表单) -- 将场景调整到比屏幕小(不管朝向),并在当前场景后面显示原始场景,这几乎相当于在一个iPad窗口中显示。

Page Sheet(页面) -- 调整场景大小,使其以纵向格式显示。

Full Screen(全屏) -- 调整场景大小,使其覆盖整个屏幕。

Current Context(当前上下文) -- 以原始场景的显示方式展示场景。

三、presentModalViewController和presentViewController的区别

presentModalViewController支持5.0,而presentViewController支持5.0以下

你可以

if (SYSTEM_VERSION_LESS_THAN(@"5.0")) {

[self presentModalViewController:self.childVC animated:YES];

} else {

[self presentViewController:self.childVC animated:YES completion:nil];

}

或直接使用

[self presentViewController:self.childVC animated:YES completion:nil];

四、 多级presentModalViewController处理

我们都知道使用弹出模态视图时有两个重要的函数presentModalViewController和dismissModalViewControllerAnimated,前面一个函数相信大家使用起来都没有问题,我想说的是后面这个函数dismissModalViewControllerAnimated,通过字面我们可以看出它的意思就是使弹出视图消失。我们设A弹出B,那么A就是presenting一方,B就是presented一方。那么该由谁来调用这个方法呢,是弹出的一方,还是被弹出的那一方呢,为此找到官方文档中如下解释:

The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, however, it automatically forwards the message to the presenting view controller.

  通过解释我们可以看出,presenting一方是负责让弹出模态视图消失的,但是系统在此处帮我们做了一个遍历就是当我们在被弹出一方调用该函数时候,系统会自动把这个消息传递到弹出它的那个VC中。

  下面我们在思考个问题,如果A弹出B,B又弹出C,此时我们通过B调用dismissModalViewControllerAnimated方法,到底是只有C被dismiss还是B和C一起被dismiss呢?

  我写了一个小程序验证了一下,程序如下:

<span style="font-weight: normal;">- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
_svVCA = [[SvViewController alloc] initWithNibName:nil bundle:nil];
self.viewController = [[[UINavigationController alloc] initWithRootViewController:_svVCA] autorelease];
[_svVCA release];
_svVCA.view.backgroundColor = [UIColor clearColor];
_svVCA.contentStr = @"A";
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
_svVCB = [[SvViewController alloc] init];
_svVCB.contentStr = @"B";
[_svVCA presentModalViewController:_svVCB animated:NO];
[_svVCB release];
_svVCC = [[SvViewController alloc] init];
_svVCC.contentStr = @"C";
[_svVCB presentModalViewController:_svVCC animated:NO];
[_svVCC release];
[_svVCB dismissModalViewControllerAnimated:NO];
//[_svVCB dismissModalViewControllerAnimated:NO];
return YES;
}
 //上面程序中我们可以看出,一开始我们创建一个A,然后添加到window中,然后弹出B,B在弹出C,接着我们就调用[_svVCB dismissModalViewControllerAnimated:NO];</span>
  运行结果如下:







上图中最左边的图是没有调用任何dismiss的情况下的结果,中间这幅图是通过B调用一次dismissModalViewControllerAnimated的结果,右边的图是连着通过B调用两次dismissModalViewControllerAnimated的结果。

通过程序测试我们可以发现当一个VC即是被弹出方(被A弹出),也是弹出方(弹出C)的时候,调用dismiss的时候是直接将其弹出的VC消失掉,而不是传递该消息到弹出它的VC去,只有当该VC没有弹出别的VC的时候才会传递消息到弹出它的VC去。这块儿可能说的有点儿绕,简单的说就是无私原则,就是B已经占了资源了,当接到释放命令的时候,就必须的先交出自己的,自己没有占有资源的时候才能尝试向上一级发出申请。



From:/article/4991322.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: