我有一个自定义容器视图控制器:ContainerVC
。它的工作是呈现两个内容视图控制器之一:ContentPortraitVC
或ContentLandscapeVC
,具体取决于当前的方向(尽管我认为容器选择其视图的原因并不重要)。 ContentPortraitVC
,在某些时候弹出ContentModalDetailVC
。
因此,有两种不同的方法可以在这里显示新内容:
父母与子女的关系(通过addChildViewController
发起并通过removeFromParentViewController
删除),
呈现和呈现的关系(通过presentViewController
发起并通过dismissViewController
删除)。
如果ContainerVC
添加了ContentPortraitVC
,然后会显示ContentModalDetailVC
,然后ContainerVC
决定切换到ContentLandscapeVC
,{{ 1}}保持可见(为什么在删除父项时不会删除它?)
但是,当要求ContentModalDetailVC
删除ContentPortraitVC
时,没有任何反应。模态显示保持不变。发生了什么事?
答案 0 :(得分:5)
使用addChildViewController
添加ContentPortraitVC
:
一个。 ContentPortraitVC
获取其parentViewController
属性集。
湾然后,您(根据Apple文档)必须手动显示ContentPortraitVC
的视图。如果您按照文档操作,则可以将其添加为ControllerVC
顶级视图的子级。
ContentPortraitVC
然后调用presentViewController
以显示ContentModalDetailVC
。
一个。这将设置其presentingViewController
属性(在调试器中显示为_parentModalViewController
ivar - 请注意,ivar与属性不同),并设置presentedModalViewController
的{{1}}属性(谁的ivar是ContentPortraitVC
)。
湾明智地看,在iPhone上,_childModalViewcontroller
的视图将完全取代ContentModalDetailVC
和ContentPortraitVC
的视图,因此只有模态视图控制器的视图才会可见。 (在iPad上,它将新UI层叠在顶部,但作为ContainerVC
视图的兄弟,而ControllerVC
的视图又是ContentPortraitVC
视图的父级)。
现在,您从ContentPortraitVC
过渡到ContentLandscapeVC
。
一个。 IOS有点神奇。它知道您要移除的内容(ContentPortraitVC
)当前有presentedViewController
个活动,因此它会更改其父级。它将nil
上的值设置为ContentPortraitVC
,获取子项(ContentModalDetailVC
)并将其父项设置为新视图(ContentLandscapeVC
)。所以现在呈现模态视图的视图控制器不再是它的呈现视图控制器。就好像ContentLandscapeVC
首先提出它一样!
湾在视图方面,您可以按照Apple文档将视图从ContentPortraitVC
更改为ContentLandscapeVC
。但您只是更改ControllerVC
视图的子视图。在iPhone上,模态视图控制器仍然是唯一显示的内容,因此进行更改不会在屏幕上执行任何操作。在iPad上,确实如此(虽然你可能不会看到它,因为模态视图通常是全屏的)。
现在你来解雇模态视图。大概是你在ContentPortraitVC
中这样做了,但它不再提及它所呈现的东西。因此,调用[self dismissViewController...
不会做任何事情,因为ContentPortraitVC
不再提供任何内容,对此的责任已转移到ContentLandscapeVC
。
这就是发生了什么以及为什么。以下是该怎么做。
当您从ContentPortraitVC
更改为ContentLandscapeVC
时,您可以手动重新连接代理,因此后者是尝试关闭模态控制器的代理。
您可以让模态控制器使用[self dismissModalControllerAnimated:YES completion:nil]
解除自身。我将要求并回答另一个问题,为什么这样有效(如果这看起来很奇怪,IOS如何知道解雇哪个?)。
您可以让ControllerVC
成为弹出模态视图的人,并负责删除它。
答案 1 :(得分:2)
如果您检查presentingViewController
上的ContentModalDetailVC
,您会看到它实际上由ContainerVC
而不是ContentPortraitVC
呈现。
要解决此问题,您只需在definesPresentationContext
上设置ContentPortraitVC
(或使用"定义上下文"复选框在Interface Builder中)。
这将告诉ContentPortraitVC
处理模式表示,而不是将响应程序链传递给定义表示上下文的下一个视图控制器(默认情况下是根视图控制器)。
您可能希望ContentLandscapeVC
定义上下文以避免同样的问题。
当两个子控制器定义自己的表示上下文时,当ContainerVC
决定交换子项时,任何模态模态将与呈现它的子项一起从新层次结构中删除。在交换之前不需要做hacky事情试图解雇:)
编辑:我应该补充一点,所呈现的视图控制器必须将modalPresentationStyle
设置为currentContext
或overCurrentContext
,