iOS 6:旋转后忽略父模式的 modalPresentationStyle

Posted

技术标签:

【中文标题】iOS 6:旋转后忽略父模式的 modalPresentationStyle【英文标题】:iOS 6: Parent modal's modalPresentationStyle ignored after rotation 【发布时间】:2012-11-12 16:55:12 【问题描述】:

对于 ios6 的 iPad,我们有这个错误,即模式视图控制器将扩展到全屏,即使它被告知 使用“表单”演示样式。但是,只有当有两个模态时才会发生这种情况,一个是父模态,一个是它的子模态。

这就是第一个模态框的创建和呈现方式:

UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[parentController presentModalViewController:navigationController animated:YES];
// parentController is my application's root controller

这是子模态的创建和呈现方式:

UINavigationController *navigationController = [[[UINavigationController alloc] initWithRootViewController:controller] autorelease];
navigationController.modalPresentationStyle = UIModalPresentationFormSheet;
[parentController presentModalViewController:navigationController animated:YES];
// parentController is the navigationController from above

因此,当从横向旋转到纵向时,父模态将扩展为全屏并保持这种状态,即使我们旋转回横向也是如此。

当我们只有父模态(没有子模态)时,它会按预期工作,即它保持表单样式。

请注意,这只发生在 iOS6(设备和模拟器)上,不会发生在 iOS 5(模拟器和测试人员报告的工作)上。

到目前为止,我尝试了以下方法但没有成功:

wantsFullScreenLayout 设置为NO 通过覆盖 wantsFullScreenLayout 来强制返回 NO 让导航控制器中的某些我的控制器也指定UIModalPresentationFormSheet 实现preferredInterfaceOrientationForPresentation 升级到 iOS 6.0.1

谢谢!


更新: 因此,我调整了来自 Apple 开发者论坛 (https://devforums.apple.com/message/748486#748486) 的回复,使其适用于多个嵌套模式。

- (BOOL) needNestedModalHack 
    return [UIDevice currentDevice].systemVersion.floatValue >= 6;


- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
                                          duration:(NSTimeInterval)duration 

    // We are the top modal, make to sure that parent modals use our size
    if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) 
        for (UIViewController* parent = self.presentingViewController;
             parent.presentingViewController;
             parent = parent.presentingViewController) 
            parent.view.superview.frame = parent.presentedViewController.view.superview.frame;
        
    

    [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];


- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
                                 duration:(NSTimeInterval)duration 
    // We are the top modal, make to sure that parent modals are hidden during transition
    if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) 
        for (UIViewController* parent = self.presentingViewController;
             parent.presentingViewController;
             parent = parent.presentingViewController) 
            parent.view.superview.hidden = YES;
        
    

    [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];


- (void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation 
    // We are the top modal, make to sure that parent modals are shown after animation
    if (self.needNestedModalHack && self.presentedViewController == nil && self.presentingViewController) 
        for (UIViewController* parent = self.presentingViewController;
             parent.presentingViewController;
             parent = parent.presentingViewController) 
            parent.view.superview.hidden = NO;
        
    

    [super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

【问题讨论】:

有人给我指出了苹果开发者论坛,我发现了这个:devforums.apple.com/message/748486 呈现多种模式显然打破了 Apple 所说的你应该做事的方式。如果您最终做这样的事情违背了 Apple 的建议,那么预计会出现这样的问题。还要考虑你可能有一个非常糟糕的设计。如果你想像这样显示多个 viewController,你应该在单个模态演示中使用包含或 navigationController。如果在 iOS 6.3 中再次出现问题,你会怎么做? @Ade:本文档提到可以链接模态视图控制器:developer.apple.com/library/ios/#featuredarticles/… 感谢您指出这一点,因为我认为您试图从单个 viewController 父级(非链接)呈现多个模态 viewController 是值得的。我个人一直在导航控制器中拥有 viewControllers。感觉自己像个混蛋;) 【参考方案1】:

不确定这是否应该被视为一个错误,我很好奇 iOS 7 会带来什么,但当前解决此问题的方法是将 modalPresentationStyle 设置为子视图控制器的 UIModalPresentationCurrentContext。

Set modalPresentationStyle = UIModalPresentationCurrentContext

这会使子级仍然以 FormSheet 的形式呈现,但会阻止父级在旋转时将大小调整为全屏。

德克

【讨论】:

这解决了我的问题。我从另一个页面表创建了页面表。在调整父页面大小后占据了我的整个屏幕。【参考方案2】:

我可以在这里看到 2 个问题。

1) 在 iOS 6 中 presentModalViewController:animated: 方法已被弃用,请尝试使用 presentViewController:animated:completion: (尽管这可能无济于事,但您仍然可能想要这样做)

2) 在 iOS 6 中,不知何故出现了容器控制器(例如 UINavigationController)不会将自动旋转消息重新发送给他们的孩子。尝试继承 UINavigationController 并重新定义相应的自动旋转方法以发送给所有子级。这可能会有所帮助。

【讨论】:

1.同意。在我写这篇文章的时候,我们仍然支持 4.3。 2. 我在测试时没有遇到问题,离现场还很远。我确实经常使用导航控制器。也许我的内容控制器足够通用,不会出现任何问题... 我想我们会在 iOS7 中看到,因为 Apple 似乎改变了旋转回调在每个主要版本上的工作方式...; -)【参考方案3】:

您需要在主视图之后实例化您的导航控制器。 这样您就可以在每个视图中管理旋转。

如果您的 AppDelegate RootViewController 是导航控制器,您将无法使用原生函数管理旋转。

【讨论】:

以上是关于iOS 6:旋转后忽略父模式的 modalPresentationStyle的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 6 上处理 iDevice 旋转

带有约束的 iOS 6.0 AutoLayout 问题:旋转时子视图消失

ios 6 旋转后模态视图大小不正确

在 ios 8 中以横向模式隐藏并在 xCode 6 中发布 ios 8 后尝试在 ios 7 中正常工作的状态栏问题

iOS 8 - 切换控件后,即使在纵向模式下,旋转也会使状态栏消失

无法在iOS 6中自动旋转