iOS旋转屏幕设置总结

作者: Phelthas | 来源:发表于2017-03-09 00:13 被阅读1536次

    iOS开发中,经常会碰到某些页面需要支持横屏显示,某些又仅支持竖屏显示,那怎么样才能比较完美的实现各个界面的横竖屏设置,有不相互影响呢?
    经过几个项目的实践比较,个人感觉让各个viewController自己来控制自己的横竖屏显示是最好的!!!
    问题是怎么设置才最简单方便不容易出错~

    注:以下全部是iOS6以后的方法,iOS6之前的太久远了,就不提了;
    这里仅涉及设置的方法,具体转屏的方法,有空再写;

    首先,要确定APP支持哪些方向

    可以通过两种方式来确定:

    1. 在工程设置处勾选


      工程设置

      或者在或者在info.plist中设置


      info.plist中设置
      这两个地方是等价的,改了其中一个地方,另一个也会跟着变;
    2. 在AppDelegate中实现方法
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
            return .allButUpsideDown
        }
    

    1或者2必须实现至少一个才行;
    什么?你说两个都没实现?那系统会按默认的.allButUpsideDown来处理。。。
    什么什么?你说两个都实现了设置的值还不一样?那系统会以AppDelegate中实现的代码为准。。。

    其次,要确定viewController支持的方向

    viewController通过以下方法来确定:

        open override var shouldAutorotate: Bool {
            return false
        }
        
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
             return .portrait
        }
        
        open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            return .portrait
        }
    

    第一个方法确定viewController是否会自动旋转,第二个方法确定viewController支持哪些方向,第三方方法确定viewController弹出来时的方向;
    需要注意的是:
    这几个方法只有当viewController是window的rootViewController或者viewController是present出来时,才会起作用!
    这几个方法只有当viewController是window的rootViewController或者viewController是present出来时,才会起作用!
    这几个方法只有当viewController是window的rootViewController或者viewController是present出来时,才会起作用!
    重要的事情说三遍

    也就是说,如果app是常见的tabBarController+navigationController+viewController的结构的话,rootViewController是tabBarController,
    所以只有tabBarController的这三个方法会被调用!
    那怎么实现开头说的让各个viewController来控制自己的方向呢?
    其实很简单,因为tabBarController和navigationController都是viewController的容器,让他们返回当前显示的viewController的相应方法就行了!
    以navigationController为例,就是:

        open override var shouldAutorotate: Bool {
            if let viewController = self.topViewController {
                return viewController.shouldAutorotate
            } else {
                return false
            }
        }
        
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let viewController = self.topViewController {
                return viewController.supportedInterfaceOrientations
            }  else {
                return .portrait
            }
        }
        
        open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            if let viewController = self.topViewController {
                return viewController.preferredInterfaceOrientationForPresentation
            }  else {
                return .portrait
            }
        }
    
    

    注意:viewController最终支持的方向是以上app支持方向和viewController支持方向两个规则的交集,如果交集为空,就会crash!!!

    基本原理知道了,也该回答最初的问题了,简单方便又不容易出错的设置方法就是

    结论:写基类

    这里需要至少三个基类,分别继承tabBarController,navigationController和viewController;
    在其中分别实现转屏方法,然后项目中所有的其他类,都继承这几个基类;
    然后,在需要支持不同方向的viewController中,重载转屏的三个方法,就大功告成了~
    例:
    这里OJSTabBarController,OJSNavigationController,OJSViewController分别集成自对应的UIViewController

    extension OJSTabBarController {
        
        //这里,如果selectedViewController是navigationController,因为navigationController也是返回它的topViewController的状态,所以最终还是各个viewController自己来控制自己的状态
        
        open override var shouldAutorotate: Bool {
            if let tempViewController = self.selectedViewController {
                return tempViewController.shouldAutorotate
            } else {
                return false
            }
        }
        
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let tempViewController = self.selectedViewController {
                return tempViewController.supportedInterfaceOrientations
            } else {
                return UIInterfaceOrientationMask.portrait
            }
        }
        
        
        open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            if let tempViewController = self.selectedViewController {
                return tempViewController.preferredInterfaceOrientationForPresentation
            } else {
                return UIInterfaceOrientation.portrait
            }
        }
    }
    
    extension OJSNavigationController {
        //这里只需要返回self.topViewController的相应属性,让各个viewController自己控制就行了
        //present出来的viewController本来就是受自己控制,跟nav无关
        
        open override var shouldAutorotate: Bool {
            if let viewController = self.topViewController {
                return viewController.shouldAutorotate
            } else {
                return false
            }
        }
        
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
            if let viewController = self.topViewController {
                return viewController.supportedInterfaceOrientations
            }  else {
                return .portrait
            }
        }
        
        
        open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            if let viewController = self.topViewController {
                return viewController.preferredInterfaceOrientationForPresentation
            }  else {
                return .portrait
            }
        }
    }
    
    
    
    extension OJSViewController {
        
        open override var shouldAutorotate: Bool {
            return false
        }
        
        open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
             return .portrait
        }
        
        open override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
            return .portrait
        }
    }
    
    

    这样做的好处是:
    每个viewController都有默认的转屏设置,不会因为漏写了代码而出现不应该出现的旋转;
    每个viewController是自己控制自己的方向,不会对前后viewController有任何影响
    需要特殊方向的viewController,仅实现自己的方法就行,不用再在rootViewController中做一大堆判断;
    。。。。。。

    彩蛋

    之前提交appstore时遇到个极其奇葩的问题,苹果审核人员用iPad装我们的iPhone app,然后发现他的iPad横着启动app时界面全乱了,
    然后他就截了个图,把我们的app拒掉了。。。。。。
    当时我的内心真是极其崩溃的,,,iPad竖着启动app时,就一切正常,横着启动app时,界面就乱套了。。。
    这想想应该是苹果的锅啊!!!
    后来偶然发现个非常规的解决方法:
    在工程设置处设置app只支持portrait,然后在AppDelegate中设置为支持其他;这样app启动的时候就会强制用竖屏方式启动,
    iPad上的问题就解决了。。。苹果也给审核通过了。。。

    有什么问题,欢迎讨论~

    相关文章

      网友评论

        本文标题:iOS旋转屏幕设置总结

        本文链接:https://www.haomeiwen.com/subject/wkpigttx.html