如何在解除模态视图控制器时保持呈现视图控制器的方向?

我有这个应用程序,我正在工作,我需要所有我的视图控制器,但一个是在肖像。 单一的视图控制器是特殊的我需要它能够旋转到任何方向的电话是在。

要做到这一点,我模式(没有embedded在NavigationController中)

所以(例如)我的结构是这样的:

  • 窗口 – 肖像
    • 根视图控制器(UINavigationController – Portrait)
      • 主视图控制器(UIViewController – Portrait)
        • 详细信息视图控制器(UIViewController – 肖像)
        • 模式视图控制器(UIVIewController – 全部)

现在,当我closures我的模式视图控制器在横向位置我的父视图控制器也被旋转,即使它不支持该方向。

应用程序中的所有UIViewControllersUINavigaionControllers都从实现这些方法的相同的一般类inheritance:

 override func supportedInterfaceOrientations() -> Int { return Int(UIInterfaceOrientationMask.Portrait.toRaw()) } 

我的模式视图控制器再次覆盖这个方法,它看起来像这样:

 override func supportedInterfaceOrientations() -> Int { return Int(UIInterfaceOrientationMask.All.toRaw()) } 

更新1

它看起来像只发生在iOS8 Beta上。 有人知道是否有什么改变视图控制器的旋转或这只是一个testing版中的错误?

 - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { if ([self.window.rootViewController.presentedViewController isKindOfClass: [SecondViewController class]]) { SecondViewController *secondController = (SecondViewController *) self.window.rootViewController.presentedViewController; if (secondController.isPresented) return UIInterfaceOrientationMaskAll; else return UIInterfaceOrientationMaskPortrait; } else return UIInterfaceOrientationMaskPortrait; } 

还有Swift

 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int { if self.window?.rootViewController?.presentedViewController? is SecondViewController { let secondController = self.window!.rootViewController.presentedViewController as SecondViewController if secondController.isPresented { return Int(UIInterfaceOrientationMask.All.toRaw()); } else { return Int(UIInterfaceOrientationMask.Portrait.toRaw()); } } else { return Int(UIInterfaceOrientationMask.Portrait.toRaw()); } } 

有关更多详情,请查看此链接

我有一个应用程序相同的问题,经过几天的实验,我想出了一个不是很好的解决scheme,但它现在工作。 我正在appdelegate中使用委托方法application:supportedInterfaceOrientationsForWindow: :。

我创build了一个testing项目,并把它放在github上 (包括一个显示结果的GIF)

//注意:它不是很快,但我希望它有帮助

经过多次实验,我确信这是iOS 8的“特色”。

如果你仔细想想,这是非常有意义的,因为它已经来了很久了。

  • 在iOS 4中,当改变标签栏控制器和导航控制器中的视图控制器以及显示/解除控制器时,可以强制应用程序旋转。

  • 然后,在iOS 6中,除了呈现/解除视图控制器(就像我在许多回答中解释的那样),强制应用程序旋转变得不可能。

  • 现在,在iOS 8中,我猜想根本不可能强制应用程序轮换(除了启动)。 它可以更喜欢某个方向,所以一旦它处于这个方向,它就会停留在那里,但是它不能强制应用程序进入这个方向。

    相反,你的视图控制器有望“适应”。 2014年有几部关于“适应”的WWDCvideo,现在我开始明白这是为什么这么重要的一个原因。

    编辑:在种子4,它看起来像这个function(强制轮换介绍和解雇)正在返回!

我们部署了一个应用程序,它具有一个横向控制器,它提供了一个只有纵向的视图控制器 在iOS 8上由苹果公司进行了审查。我们只重写supportedInterfaceOrientations。

值得注意的是,我们发现了beta 3,4和5之间的很多不同之处。最后,我们不得不等待通用汽车在共同努力之前更新我们的iOS 8应用程序。

你需要在iOS 8非常小心,以确保你不这样做:

 [self dismissViewControllerAnimated:YES completion:nil] [self presentViewController:vc animated:YES completion:nil] 

如果传出的vc是纵向的,而传入的是横向的,那么一些视图帧可能会非常混乱。 代之以在解除呼叫的完成块中呈现传入的vc。

 [self dismissViewControllerAnimated:YES completion:^{ [self presentViewController:vc animated:YES completion:nil] }]; 

在根视图控制器中,尝试添加:

 - (NSUInteger)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } 

为我工作。

Swift 3.0或更高版本,只需检查呈现的视图控制器的“isBeingDismissed”属性。 下面是示例代码,这是在呈现视图控制器被解散之后立即向video模式呈现视图控制器。

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) { if rootViewController.canRotateVC == true { if baseVC.isBeingDismissed == false { return .allButUpsideDown } } } return .portrait} 

您可以通过以下代码获取topController:

  private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController?{ if (rootViewController == nil) { return nil }if (rootViewController.isKind(of: (UITabBarController).self)) { return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController) } else if (rootViewController.isKind(of:(UINavigationController).self)) { return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController) } else if (rootViewController.presentedViewController != nil) { return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController) } return rootViewController } 

这实际上更容易,可以没有任何额外的属性(这是AVPlayerViewController的一个例子):

 - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { if ([self.window.rootViewController.presentedViewController isKindOfClass: [AVPlayerViewController class]]) return self.window.rootViewController.presentedViewController.isBeingDismissed ? UIInterfaceOrientationMaskPortrait : UIInterfaceOrientationMaskAll; else return UIInterfaceOrientationMaskPortrait; } else { return UIInterfaceOrientationMaskAll; } } 

真棒问题和由@ZeEeM ZaFaR提供的真棒答案! 把他的答案和这个结合起来,使我得到了一个更好,更通用的解决scheme。

第一个答案的缺点是你必须在每个允许旋转的视图控制器中pipe理variablesisPresented 。 此外,您必须展开检查,并为每个允许轮换的vc在supportedInterfaceOrientationsForWindow投射。

第二个答案的缺点是不起作用; 当解除所呈现的vc时它也旋转呈现的vc。

这个解决scheme允许在你放置canRotate(){}的所有vc中旋转,并且不会旋转呈现的vc。

Swift 3:
在AppDelegate.swift中:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { if let rootViewController = self.topViewControllerWithRootViewController(rootViewController: window?.rootViewController) { if (rootViewController.responds(to: Selector(("canRotate")))) { // Unlock landscape view orientations for this view controller if it is not currently being dismissed if !rootViewController.isBeingDismissed{ return .allButUpsideDown } } } // Only allow portrait (standard behaviour) return .portrait } private func topViewControllerWithRootViewController(rootViewController: UIViewController!) -> UIViewController? { if (rootViewController == nil) { return nil } if (rootViewController.isKind(of: UITabBarController.self)) { return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UITabBarController).selectedViewController) } else if (rootViewController.isKind(of: UINavigationController.self)) { return topViewControllerWithRootViewController(rootViewController: (rootViewController as! UINavigationController).visibleViewController) } else if (rootViewController.presentedViewController != nil) { return topViewControllerWithRootViewController(rootViewController: rootViewController.presentedViewController) } return rootViewController } 

在允许旋转的每个视图控制器中:

 func canRotate(){} 

我有同样的问题,终于find了一个解决scheme,在另一个UIWindow中打开模式视图控制器,它工作顺利。

堆栈 – iOS8 – 防止呈现viewController旋转

代码: https : //github.com/OrenRosen/ModalInWindow