使用Swift在一个ViewController中强制使用横向模式

时间:2014-11-20 10:55:50

标签: ios swift landscape

我试图在横向模式的应用程序中强制只有一个视图, 我在打电话

override func shouldAutorotate() -> Bool {
    print("shouldAutorotate")
    return false
}

override func supportedInterfaceOrientations() -> Int {
    print("supportedInterfaceOrientations")
    return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return UIInterfaceOrientation.LandscapeLeft
}

视图以纵向模式启动,并在更改设备方向时保持旋转。
永远不会调用shouldAutorotate 任何帮助将不胜感激。

19 个答案:

答案 0 :(得分:60)

它可能对其他人有用,我找到了一种强制视图以横向模式启动的方法:

将它放在viewDidLoad()中:

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")

override var shouldAutorotate: Bool {
    return true
}

答案 1 :(得分:46)

Swift 4

override func viewDidLoad() {
    super.viewDidLoad()
    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeLeft
}

override var shouldAutorotate: Bool {
    return true
}

//如果您的视图嵌入在导航控制器中,则仅上述操作无效。你必须级联 //所以在类定义

之后添加以下扩展名
extension UINavigationController {

override open var shouldAutorotate: Bool {
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.preferredInterfaceOrientationForPresentation
        }
        return super.preferredInterfaceOrientationForPresentation
    }
}

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask{
    get {
        if let visibleVC = visibleViewController {
            return visibleVC.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }
}}

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    let value = UIInterfaceOrientation.landscapeLeft.rawValue
    UIDevice.current.setValue(value, forKey: "orientation")
}

private func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.landscapeLeft
}

private func shouldAutorotate() -> Bool {
    return true
}

答案 2 :(得分:19)

Swift 4 ,测试 iOS 11

您可以在 projectTarget - >中指定方向一般 - > DeploymentInfo(设备方向) - >肖像(Landscapeleft和Landscaperight是可选的)

<强>的AppDelegate

    var myOrientation: UIInterfaceOrientationMask = .portrait
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return myOrientation
    }

<强> LandScpaeViewController

override func viewDidLoad() {
        super.viewDidLoad()
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .landscape
}

<强> OnDismissButtonTap

let appDelegate = UIApplication.shared.delegate as! AppDelegate
 appDelegate.myOrientation = .portrait

多数民众赞成。 :)

答案 3 :(得分:18)

使用Swift 2.2

尝试:

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

跟着:

UIViewController.attemptRotationToDeviceOrientation()

来自Apple的UIViewController类参考:

  

某些视图控制器可能希望使用特定于应用程序的条件来确定支持哪些接口方向。如果您的视图控制器执行此操作,当这些条件发生更改时,您的应用程序应调用此类方法。系统会立即尝试旋转到新方向。

然后,正如其他人所建议的那样,根据需要覆盖以下方法:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
    return true
}

我在签名视图中遇到了类似的问题,这为我解决了这个问题。

答案 4 :(得分:9)

对我来说,最好的结果来自Zeesha的回答和sazz的回答。

将以下行添加到AppDelegate.swift:

var orientationLock = UIInterfaceOrientationMask.portrait
var myOrientation: UIInterfaceOrientationMask = .portrait
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return myOrientation
}  

将以下行添加到视图控制器类:

let appDel = UIApplication.shared.delegate as! AppDelegate

将以下行添加到视图控制器的viewDidLoad()

appDel.myOrientation = .landscape
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")

(可选)将此行添加到您的解散功能:

appDel.myOrientation = .portrait
UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")

这些代码行的作用是将默认方向设置为纵向,在视图控制器加载时将其旋转,然后在视图控制器关闭后最终将其重置为纵向。

答案 5 :(得分:6)

我需要强制一个控制器进入纵向。添加这个对我有用。

使用iOS 11的swift 4

override var   supportedInterfaceOrientations : UIInterfaceOrientationMask{

    return  .portrait

}

答案 6 :(得分:4)

覆盖(在ViewController中):

override public var shouldAutorotate: Bool {
    return false
} 

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .landscapeRight
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeRight
}

ios 13的提示从ios 13开始,VC与modalPresentationStyle具有不同的.automatic,并且设备存在模式视图而不是全屏VC。要解决此问题,必须将modalPresentationStyle设置为.fullScreen。示例:

let viewController = YourViewController()
viewController.modalPresentationStyle = .fullScreen

答案 7 :(得分:2)

Swift 3.每次用户重新打开应用程序时,都会锁定方向。

class MyViewController: UIViewController {
    ...
    override func viewDidLoad() {
        super.viewDidLoad()

        // Receive notification when app is brought to foreground
        NotificationCenter.default.addObserver(self, selector: #selector(self.onDidBecomeActive), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil)
    }

    // Handle notification
    func onDidBecomeActive() {
        setOrientationLandscape()
    }

    // Change orientation to landscape
    private func setOrientationLandscape() {
        if !UIDevice.current.orientation.isLandscape {
            let value = UIInterfaceOrientation.landscapeLeft.rawValue
            UIDevice.current.setValue(value, forKey:"orientation")
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }

    // Only allow landscape left
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.landscapeLeft
    }

    /*
    // Allow rotation - this seems unnecessary
    private func shouldAutoRotate() -> Bool {
        return true
    }
    */
    ...
}

答案 8 :(得分:2)

适用于Swift 2.2

 func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if self.window?.rootViewController?.presentedViewController is SignatureViewController {

        let secondController = self.window!.rootViewController!.presentedViewController as! SignatureViewController

        if secondController.isPresented {

            return UIInterfaceOrientationMask.LandscapeLeft;

        } else {

            return UIInterfaceOrientationMask.Portrait;
        }

    } else {

        return UIInterfaceOrientationMask.Portrait;
    }
}

答案 9 :(得分:1)

Swift 4

尝试保持方向不起作用,但这对我来说:

...        
override func viewDidLoad() {
       super.viewDidLoad()
       forcelandscapeRight()
       let notificationCenter = NotificationCenter.default
       notificationCenter.addObserver(self, selector: #selector(forcelandscapeRight), name: Notification.Name.UIDeviceOrientationDidChange, object: nil)
    }

    @objc func forcelandscapeRight() {
        let value = UIInterfaceOrientation.landscapeRight.rawValue
        UIDevice.current.setValue(value, forKey: "orientation")
    }
....

答案 10 :(得分:1)

在ViewController中的viewDidLoad方法下方的函数调用

func rotateDevice(){
    UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
    UIView.setAnimationsEnabled(true) // while rotating device it will perform the rotation animation
}`
  

App委托文件在函数和变量下方添加

//Orientation Variables
var orientationLock = UIInterfaceOrientationMask.portrait
var myOrientation: UIInterfaceOrientationMask = .portrait

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return .landscape }

答案 11 :(得分:0)

根据documentation of supportedInterfaceOrientationsshouldAutorotate方法应在Objective-C中返回trueYES,以便考虑supportedInterfaceOrientations

答案 12 :(得分:0)

我的解决方法是

仅在AppDelegate中的代码下面添加了

enum PossibleOrientations {
  case portrait
    case landscape

    func o() -> UIInterfaceOrientationMask {
      switch self {
      case .portrait:
        return .portrait
      case .landscape:
        return .landscapeRight
      }
    }
}
var orientation: UIInterfaceOrientationMask = .portrait

func switchOrientation(to: PossibleOrientations) {
    let keyOrientation = "orientation"

    if to == .portrait && UIDevice.current.orientation.isPortrait {
        return
    } else if to == .landscape && UIDevice.current.orientation.isLandscape {
        return
    }

    switch to {
    case .portrait:
        orientation = .portrait
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: keyOrientation)
    case .landscape:
        orientation = .landscapeRight
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: keyOrientation)
    }
}

并调用以下代码进行更改

override func viewDidLoad() {
    super.viewDidLoad()

    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.switchOrientation(to: .landscape)
    }
}

或如下所示

@IBAction func actBack() {
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        appDelegate.switchOrientation(to: .portrait)
    }
    self.navigationController?.popViewController(animated: true)
}

答案 13 :(得分:0)

// below code put in view controller
// you can change landscapeLeft or portrait

override func viewWillAppear(_ animated: Bool) {
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
    }

override var shouldAutorotate: Bool {
        return true
    }
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeRight
    }
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeRight
    }

答案 14 :(得分:0)

在AppDelegate中添加此

//Orientation Variables
    var myOrientation: UIInterfaceOrientationMask = .portrait

    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
    {
        return myOrientation

    }

将其添加到要更改方向的viewController中

override func viewDidLoad() {
        super.viewDidLoad()
        self.rotateToLandsScapeDevice()
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        self.rotateToPotraitScapeDevice()
    }

    func rotateToLandsScapeDevice(){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .landscapeLeft
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
        UIView.setAnimationsEnabled(true)
    }

    func rotateToPotraitScapeDevice(){
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        appDelegate.myOrientation = .portrait
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
        UIView.setAnimationsEnabled(true)
    }

答案 15 :(得分:0)

我在项目中遇到了类似的问题。它仅支持人像。 ViewController的结构是,Navigation包含一个控制器(我称为A)和一个A控制器中的长Scrollview。我需要A(纵向)到B(横向右边)。

在一开始,我尝试了下面的方法,它似乎可以工作,但最终我发现了一个错误。

Swift 5和iOS12

// In B controller just override three properties

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.landscapeRight
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .landscapeRight
}

然后某些事情变得奇怪。当控制器B向控制器A撤消时。控制器A中的ScrollView已滑到某个点。

因此,我使用了另一种方法,因此在viewWillAppear时旋转屏幕。您可以在下面查看其代码。

// In controller B
// not need override shouldAutorotate , supportedInterfaceOrientations , preferredInterfaceOrientationForPresentation

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    let appDel = UIApplication.shared.delegate as! AppDelegate
    appDel.currentOrientation = .landscapeRight
    UIDevice.current.setValue( UIInterfaceOrientation.landscapeRight.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation()
}

//in viewWillDisappear rotate to portrait can not fix the bug


override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
    let appDel = UIApplication.shared.delegate as! AppDelegate
    appDel.currentOrientation = .portrait
    UIDevice.current.setValue( UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
    UIViewController.attemptRotationToDeviceOrientation() //must call 
    super.dismiss(animated: true, completion: nil)
}
// in AppDelegate
// the info plist is only supported portrait also, No need to change it

var currentOrientation : UIInterfaceOrientationMask = .portrait


func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return self.currentOrientation
}

答案 16 :(得分:0)

我尝试了以下许多答案,但恐怕它们没有用。特别是如果导航栏和标签栏也已在应用程序上实现。 Sunny Lee在以下文章中提供了对我有用的解决方案: Sunny Lee, Medium post

这是该帖子的更新: Original solution

实现帖子的解决方案时,我所做的唯一更改是将引用.allButUpsideDown的部分更改为.landscapeleft

答案 17 :(得分:0)

在带有Swift 5的Xcode 11中,我实现了以下内容。但是,仅当项目目标的设备方向未包括所有方向时,该方法才有效。我禁用了“颠倒”检查。在此之后,以下代码起作用。如果启用了所有复选框,则不会调用该代码;

class MyController : UINavigationController {

    override var shouldAutorotate: Bool {
        return true
    }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscape
    }


}

答案 18 :(得分:-3)

class CustomUIViewController : UIViewController{

    override var   supportedInterfaceOrientations : UIInterfaceOrientationMask{

        return  .landscapeLeft

    }

}


class ViewController: CustomUIViewController {
.
.
.
}