presentingViewController和presentedViewController以及dismissViewControllerAnimated的使用

文章的由来:

偶然在一次想要判断当前控制器是通过present模态推出还是通过push入栈显示的时候注意到了presentingViewController和presentedViewController两个属性,即:如果presentingViewController不为空,则当前控制器是通过present模态推出的方式显示的,那么相应的返回方式应该是dismiss而不是pop,之后又在头文件看到还有一个presentedViewController,就研究了下这两个属性的具体意义

文档中的presentingViewController和presentedViewController

presentingViewController

The view controller that presented this view controller.
When you present a view controller modally (either explicitly or implicitly) using the presentViewController:animated:completion: method, the view controller that was presented has this property set to the view controller that presented it. If the view controller was not presented modally, but one of its ancestors was, this property contains the view controller that presented the ancestor. If neither the current view controller or any of its ancestors were presented modally, the value in this property is nil.

大意是:呈现此视图控制器的视图控制器。
当您使用presentViewController:animated:completion: 方法(显式或隐式地)呈现一个视图控制器时,呈现的视图控制器将这个属性设置为呈现它的视图控制器。如果视图控制器不是以模态【present】呈现的,但是它的上一级是,这个属性包含呈现上一级的视图控制器。如果当前视图控制器或它的任何上一级都没有以模态方式显示,则此属性中的值为nil。

举例说明:

有五个控制器 ABCDE,应用启动先显示根控制器A,之后A通过present方式推出带导航栏的B,B再通过push的方式推出C,C再通过push的方式推出D,D再通过push的方式推出E,那么E的 presentingViewController 就是 B
也就是presentingViewController即为当前控制器的上级控制器【即父级控制器】,并且是通过present方式显示的父级,上面例子中只有B是通过present方式推出的,且B是CDE的父级,那么 D 的presentingViewController也将是B,大家可以自己理解一下
同理:如果还是有五个控制器 ABCDE,应用启动先显示根控制器A,之后全部是通过present方式依次推出 B、C、D、E,那么,这个时候E的presentingViewController就是D了,D的presentingViewController就是C

哈哈哈,会不会说的有点多,其实自己看看概念慢慢想就会想通的,后面会再介绍一下这个属性有什么用,会用在哪种场景

presentedViewController

The view controller that is presented by this view controller, or one of its ancestors in the view controller hierarchy.
When you present a view controller modally (either explicitly or implicitly) using the presentViewController:animated:completion: method, the view controller that called the method has this property set to the view controller that it presented. If the current view controller did not present another view controller modally, the value in this property is nil.

大意是:视图控制器由该视图控制器呈现,或其在视图控制器层次结构中的祖先之一。
当您使用presentViewController:animated:completion: method方法以模态(显式或隐式)方式呈现一个视图控制器时,调用该方法的视图控制器将这个属性设置为它所呈现的视图控制器。如果当前视图控制器没有以模式显示另一个视图控制器,则此属性中的值为nil。

举例说明:

有两个控制器AB,A通过present模态推出B,那么A的presentedViewController就是B,也就是你通过present模态推出了谁,你的presentedViewController就是谁,这样就好理解了,哈哈,这个属性就是这么简单,当然,如果没有模态推出任何控制器,那么属性值就是nil

嗯,剩下一个dismissViewControllerAnimated这个方法解释完,就不会愧对我的标题了🙃,这个方法有两种使用方式哦,跟着我继续看吧......

还是先看文档解释

Dismisses the view controller that was presented modally by the view controller.
The presenting view controller is responsible for dismissing the view controller it presented. If you call this method on the presented view controller itself, UIKit asks the presenting view controller to handle the dismissal.
If you present several view controllers in succession, thus building a stack of presented view controllers, calling this method on a view controller lower in the stack dismisses its immediate child view controller and all view controllers above that child on the stack. When this happens, only the top-most view is dismissed in an animated fashion; any intermediate view controllers are simply removed from the stack. The top-most view is dismissed using its modal transition style, which may differ from the styles used by other view controllers lower in the stack.
If you want to retain a reference to the view controller'��s presented view controller, get the value in the presentedViewControllerproperty before calling this method.
The completion handler is called after the viewDidDisappear: method is called on the presented view controller.

大意是【这里我就不用翻译软件翻译了,翻译的都不够准确,直接是我自己的理解,大家认为有什么不准确的欢迎指出】:
这个方法是用来将某一个通过present模态显示的视图控制器取消掉模态显示
如果连续模态推出了多个控制器,并在最上一级控制器执行了该方法,则会从最上一级控制器开始,后面所有通过present显示的控制器都会被dismiss掉,且这些控制器在被dismiss的时候仍然会执行viewWillAppear以及viewDidDisappear等相关视图显示或消失的方法,但是消失的过程却是一瞬间的,不论中间多少个控制器,你看到的效果就像只dismiss了一个控制器一样

举例说明:有5个控制器ABCDE,应用启动后显示根控制器A,之后Apresent出B,B present出C ,,,,一直到E,那么等到E完全显示的这个时候,如果A执行了dismiss,你将会看到B消失的动画,同时,CDE也会被dismiss,实际上dismiss的顺序和你present的顺序一致,即从E->D->C->B,然而只有B才会有dismiss的推出动画,想必是苹果对这一部分做了优化

进入正题进入正题进入正题进入正题进入正题进入正题进入正题进入正题

前面说到了dismissViewControllerAnimated有两种用法,其实大家从文档中就应该发现这个方法是用来取消掉某一个控制器的模态显示的,那么是谁来取消掉的呢?一般大家都是这么写的吧,如下:
[self dismissViewControllerAnimated:YES completion:nil];
这么写的含义是:让系统【即UIKIT框架内部处理】将当前控制器dismiss掉

但实际上,我们应该这么写:
if (self.presentingViewController) { [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; } else { [self dismissViewControllerAnimated:YES completion:nil]; }
这么写的含义是:当前显示的控制器是由谁模态推出的就由谁来dismiss掉,如果是最上一级的就交给系统来dismiss,因为最上一层没有presentingViewController,为啥没有,大家再回去对照presentingViewController的概念,哈哈哈哈,看看B的presentingViewController是不是没有

最后就是应用场景了:

如果多个控制器都通过 present 的方式跳转呢?比如从A跳转到B,从B跳转到C,从C跳转到D,如何由D直接返回到A呢?可以通过 presentingViewController 一直找到A控制器,然后调用A控制器的 dismissViewControllerAnimated 方法。方法如下:
UIViewController *controller = self; while(controller.presentingViewController != nil){ controller = controller.presentingViewController; } [controller dismissViewControllerAnimated:YES completion:nil];
PS:如果不是想直接返回到A控制器,比如想回到B控制器,while循环的终止条件可以通过控制器的类来判断。

OK,打完收工,装逼要有限度🙃

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,961评论 5 473
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,444评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,009评论 0 333
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,082评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,101评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,271评论 1 278
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,738评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,395评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,539评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,434评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,481评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,160评论 3 317
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,749评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,816评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,038评论 1 256
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,548评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,140评论 2 341

推荐阅读更多精彩内容