ios中使用PresentModalViewController和dismissModalViewControllerAnimated的总结

来源:互联网 发布:交互流程图软件 编辑:程序博客网 时间:2024/05/06 07:14

一、主要用途

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

  1、收集用户输入信息

  2、临时呈现一些内容

  3、临时改变工作模式

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

  5、显示一个新的view层级

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

但是在ios5.0之后,dismissModalViewControllerAnimated方法被 dismissViewControllerAnimated:completion:方法所取代.后者比前者多了一个(void (^)(void))completion参数,这个参数是一个block用来提供UIViewcontroller对象被释放之后运行的回调.这个block的回调方法是在UIViewcontroller的viewDidDisappear: 之后被调用.

    与以上的两个方法对应的方法是presentModalViewController:animated:和presentViewController:animated:completion:.

例如:

[self dismissViewControllerAnimated:YES completion:^{}];

[self presentViewController:musicPicker animated:YES completion:^{}];



二、几个概念和常用设置

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。

二、详细解释


在实际开发中,如果要弹出视图:
我们常用到presentModalViewController方法和dismissModalViewControllerAnimated方法。
presentModalViewController:弹出视图
dismissModalViewControllerAnimated隐藏视图

贴代码:

弹出视图:

FeedbackViewController *feedbackViewController = [[FeedbackViewController alloc]initWithNibName:@"FeedbackViewController" bundle:nil];

    UINavigationController *navigationController = [[UINavigationController alloc]initWithRootViewController:feedbackViewController];

    [self presentModalViewController:navigationController animated:YES];


隐藏视图:

[self dismissModalViewControllerAnimated:YES];


关于这两个方法的几点说明:

1.iPhone上弹出/隐藏 视图时,使用为全屏模式

On iPhone and iPod touch devices, the view of modalViewController is always presented full screen.

2.搞清楚谁是presenting,谁是presented

如果A弹出B,那么A为presenting,B为presented

3.隐藏视图的策略

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.

我们假如A弹出B
就是说,A负责隐藏B;如果我们在B中调用dismissModalViewControllerAnimated方法,那么编译器,自动将消息发送给A。
等等,什么消息?
简单的理解,当执行presentModalViewController:方法:在A弹出B时:

执行A的viewWillDisappear方法,
通知B执行自己的viewWillAppear方法和viewDidAppear方法
执行A的viewDidDisappear方法

当执行dismissModalViewControllerAnimated方法:隐藏B时:

执行B的viewWillDisappear
通知A执行自己的viewWillAppear方法和viewDidAppear方法
执行B的viewDidDisappear方法

以下我做了个测试来输出一轮AB切换:
A:More
B:Feed

2012-12-27 14:01:23.666 WTV[1627:11303] -More--viewWillDisappear----

2012-12-27 14:01:23.672 WTV[1627:11303] -Feed--viewWillAppear----

2012-12-27 14:01:24.086 WTV[1627:11303] -Feed--viewDidAppear----

2012-12-27 14:01:24.087 WTV[1627:11303] -More--viewDidDisappear----

2012-12-27 14:01:25.745 WTV[1627:11303] -Feed--viewWillDisappear----

2012-12-27 14:01:25.745 WTV[1627:11303] -More--viewWillAppear----

2012-12-27 14:01:26.156 WTV[1627:11303] -More--viewDidAppear----

2012-12-27 14:01:26.157 WTV[1627:11303] -Feed--viewDidDisappear----


当我们信心慢慢,庆幸我们可以了解了这两个方法时,悲剧发生了:

4.苹果官方已经把这两个方法 Deprecated in iOS 6.0. 

- (void)presentModalViewController:(UIViewController *)modalViewController animated:(BOOL)animated;


- (void)dismissModalViewControllerAnimated:(BOOL)animated;


取而代之的是:

[self presentViewController:navigationController

                       animated:YES

                     completion:^(void){

                         // Code

                     

                     }];


[self dismissViewControllerAnimated:YES

                             completion:^(void){

                                 // Code

                             }];


新接口的差别是提供了一个参数,允许你传入一个block。这个block的回调方法在VC的viewWillDisappear方法后调用。也就是被隐藏的VC对象被释放后运行回调。
这样做的好处:可以方便做多个UI效果之间的衔接和转换。



0 0