【问题标题】:How to change viewController based on device orientation如何根据设备方向更改 viewController
【发布时间】:2015-10-30 21:30:56
【问题描述】:

在过去的几天里,我一直在想办法做到这一点:

如果处于横向模式,请更改为 CollectionViewController。如果处于纵向模式,请更改为 ViewController。

与音乐应用的行为方式差不多。

我的做法是在我的主要 PortraitViewController 类中实现 viewWillTransitionToSize():

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 和一个 searchController,顶部有一个 searchBar。

在故事板中,portraitViewController 嵌入在导航控制器中,collectionViewController(landscapeViewController) 是独立的。

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

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

不允许在解除分配时尝试加载视图控制器的视图,这可能会导致未定义的行为 (UISearchController)

有人可以指出这里出了什么问题吗?如果有任何可以帮助的教程/示例,我将不胜感激!非常感谢您的帮助

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

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)
        }
    }

【问题讨论】:

    标签: ios iphone swift uiviewcontroller screen-orientation


    【解决方案1】:

    这些警告或错误的原因是在关闭和展示视图控制器时存在延迟,并且您对展示和关闭的调用相互重叠。

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

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

    为了防止这些问题,需要确保在呈现新视图控制器之前完成解除。这可以通过使用解除方法中的完成处理程序处理状态并添加对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)
            }
        }
    }
    

    【讨论】:

    • 非常感谢!现在我知道它为什么会抛出这些错误。但是我注意到当我返回纵向视图时,导航栏不见了。这是因为我只展示了纵向视图控制器,而不是纵向视图控制器嵌入的导航控制器吗?
    • 不客气。您可以通过在故事板中实例化它来获取导航栏,如storyboard.instantiateViewControllerWithIdentifier(" ") as? UINavigationController 并呈现导航控制器。您可能需要将它们添加到您的故事板中,并使用 show segue 将它们连接到您的 VC。据我所知,模态演示不使用以前的导航控制器堆栈。另一种方法是将视图控制器推送/弹出到现有的 NC 堆栈上。
    • 在竖屏模式下,我声明let navC = storyBoard.instantiateViewControllerWithIdentifier("navID") as! UINavigationController,然后使用navC.pushViewController(portraitVC, animated: true),现在所有警告都消失了。需要深入研究如何呈现 viewController 但我想我在这里得到了一些基本概念。再次感谢!
    • 很高兴听到这个消息。我希望你能以你想要的方式得到它。您可能还想查看尺寸等级作为根据方向处理不同视图的另一种选择。它们不能替代真正理解呈现视图控制器,就像您正在做的那样,因为这是更基本的。
    猜你喜欢
    • 1970-01-01
    • 2021-11-11
    • 1970-01-01
    • 1970-01-01
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多