如何根据设备方向更改 viewController

How to change viewController based on device orientation

最近几天我一直在想办法做到这一点:

如果处于横向模式,则更改为收藏ViewController。如果在纵向模式下,请更改为 ViewController。

几乎与音乐应用程序的行为方式相同。

我的方法是在我的主肖像中实现 viewWillTransitionToSize()ViewController class:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    let storyBoard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
    let portraitViewController = storyBoard.instantiateViewControllerWithIdentifier("portraitViewController") as! ViewController
    let landscapeViewController = storyBoard.instantiateViewControllerWithIdentifier("landscapeViewController") as! beerCollectionViewController

    if (UIDevice.currentDevice().orientation.isLandscape) {
        // In landscape

        presentViewController(landscapeViewController, animated: true, completion: nil)

    } else {
        // In portrait

        self.navigationController?.presentViewController(portraitViewController, animated: true, completion: nil)
       //let navVC = UINavigationController(rootViewController: portraitViewController)
       //presentViewController(navVC, animated: true, completion: nil)

        //Dismiss collectionViewController after switching back to portrait
        self.dismissViewControllerAnimated(true, completion: nil)
    }

}

Main viewController(portraitViewController) 包含一个 tableview 和一个顶部有 searchBar 的 searchController。

在情节提要中,肖像ViewController嵌入在导航控制器中,集合ViewController(风景ViewController)是独立的。

它运行,但我收到以下 2 个警告:

尝试在视图不在 window 层次结构中的 ViewController 上呈现 UINavigationController!

不允许在视图控制器释放时加载它的视图,这可能会导致未定义的行为 (UISearchController)

有人能指出这里出了什么问题吗?如果有任何 tutorial/examples 可以提供帮助,我将不胜感激!非常感谢您的帮助

编辑: 这是有效的最终代码

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    let storyBoard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())

    // In landscape
    if UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation) {
        let landscapeVC = storyBoard.instantiateViewControllerWithIdentifier("landscapeViewController") as! beerCollectionViewController
        if presentedViewController != nil {
            if !presentedViewController!.isBeingDismissed() {
                self.dismissViewControllerAnimated(false, completion:  {
                    self.presentViewController(landscapeVC, animated: true, completion: nil)
                })
            }
        } else {
            self.presentViewController(landscapeVC, animated: true, completion: nil)
        }

    }
    // In portrait
    else {
        let navC = storyBoard.instantiateViewControllerWithIdentifier("navID") as! UINavigationController
        let portraitVC = storyBoard.instantiateViewControllerWithIdentifier("portraitViewController") as! ViewController

        if presentedViewController != nil {
            if !presentedViewController!.isBeingDismissed() {
                self.dismissViewControllerAnimated(false, completion:  {
                    navC.pushViewController(portraitVC, animated: true)
                })
            }
        } else {
            navC.pushViewController(portraitVC, animated: true)
        }
    }

出现这些警告或错误的原因是解散和呈现视图控制器时存在延迟,并且您对呈现和解散的调用相互重叠。

第一个报告视图不在层次结构中的错误意味着您正试图在原始视图控制器或导航控制器上呈现一个视图,该视图不再可用,因为另一个视图控制器已被模态呈现。

关于在释放视图时加载视图的第二个错误表明,当尝试另一个模式呈现时,视图控制器解除尚未完全完成。

为了防止这些问题,需要确保在呈现新的视图控制器之前完成解雇。这可以通过使用 dismiss 方法中的完成处理程序处理状态并添加对 isBeingDismissed 状态的检查来实现。

下面是一些实现该功能的代码:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)

    let storyboard = UIStoryboard(name: "Main", bundle: nil)

    if UIDeviceOrientationIsLandscape(UIDevice.currentDevice().orientation) {
        let landscapeVC = storyboard.instantiateViewControllerWithIdentifier("landscapeViewController") as! beerCollectionViewController

        if presentedViewController != nil {
            if !presentedViewController!.isBeingDismissed() {
                dismissViewControllerAnimated(false, completion:  {
                    self.presentViewController(landscapeVC!, animated: true, completion: nil)
                })
            }
        } else {
            self.presentViewController(landscapeVC!, animated: true, completion: nil)
        }
    } else { // Portrait
        let portraitVC = storyboard.instantiateViewControllerWithIdentifier("portraitViewController") as! ViewController

        if presentedViewController != nil {
            if !presentedViewController!.isBeingDismissed() {
                dismissViewControllerAnimated(false, completion:  {
                    self.presentViewController(portraitVC!, animated: true, completion: nil)
                })
            }
        } else {
            self.presentViewController(portraitVC!, animated: true, completion: nil)
        }
    }
}