美文网首页程序员
APP内单个VC支持Landscape

APP内单个VC支持Landscape

作者: Dev端 | 来源:发表于2016-06-22 16:24 被阅读158次

    昨天在做App内视频播放器模块碰到的问题, 要达到的效果如下:
    App本身是要只支持Portrait的,当且仅当到达视频播放器的时候支持Landscape.

    讲道理应该会有强制设备旋转的方法,在StackOverflow上有这样一个问题: How to force view controller orientation in iOS 8?,投票第一的答案就是解决这个问题的,然而iOS9这个方法已经无用.

    let value = UIInterfaceOrientation.LandscapeLeft.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
    

    修复强制旋转屏幕的可用性的办法是修改AppDelegate里的一个方法:

    func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if let topController = UIViewController.topMostViewController() {
            if topController is XXViewController {
                return [.Portrait, .LandscapeLeft]
            }
        }
        return [.Portrait]
    }
    

    这个方法在每次设备检测到屏幕有旋转倾向的时候都会被调用,包括内部调用和外部旋转, 这里找到最上层的ViewController, 判定当且仅当顶层是特定的ViewController的时候才会支持LandScape.

    这样设置之后,强制旋转屏幕的KVO方法又再次生效了:

    let value = UIInterfaceOrientation.LandscapeLeft.rawValue
    UIDevice.currentDevice().setValue(value, forKey: "orientation")
    

    然而,这两行代码始终还是不安全的,指不定哪天苹果又用一些新的方法去限制这种强制调用. 其实真正正确的做法是在项目Target->Device Orientation里勾上所有有可能支持的orientation,然后在每个VC里重写下面这个方法来对VC做出限制.

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return [.Portrait]
    }
    

    但是面临的问题就是每一个VC都要多这3行代码. 囧.

    有时候hacking还是不hacking,难选择呢....

    最后贴一下Utils Func:

    extension UIViewController {
    
        /// Returns the current application's top most view controller.
        public class func topMostViewController() -> UIViewController? {
            let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
            return self.topMostViewControllerOfViewController(rootViewController)
        }
    
    
    
        /// Returns the top most view controller from given view controller's stack.
        class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
            // UITabBarController
            if let tabBarController = viewController as? UITabBarController,
               let selectedViewController = tabBarController.selectedViewController {
                return self.topMostViewControllerOfViewController(selectedViewController)
            }
    
            // UINavigationController
            if let navigationController = viewController as? UINavigationController,
               let visibleViewController = navigationController.visibleViewController {
                return self.topMostViewControllerOfViewController(visibleViewController)
            }
    
            // presented view controller
            if let presentedViewController = viewController?.presentedViewController {
                return self.topMostViewControllerOfViewController(presentedViewController)
            }
    
            // child view controller
            for subview in viewController?.view?.subviews ?? [] {
                if let childViewController = subview.nextResponder() as? UIViewController {
                    return self.topMostViewControllerOfViewController(childViewController)
                }
            }
    
            return viewController
        }
    
    }
    

    相关文章

      网友评论

        本文标题:APP内单个VC支持Landscape

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