Lock one view orientation in iOS - ios

I'm trying to lock one view of my app in portrait mode. I have a top navigation controller view and multiple nested scenes.
I found many answers to lock orientation question and tried the code below, but it works only partially. Let the scenes A and B, where A has a segue to B, and B is locked in portrait orientation. If I go to the B scene, turn the device to the landscape position and back to A, the orientation is inherited from previous B (portrait).
How can I make the A scene recognize the actual device orientation?
Navigation controller
internal override func shouldAutorotate() -> Bool {
return visibleViewController!.shouldAutorotate()
}
"B" View controller
override func shouldAutorotate() -> Bool {
if UIDevice.currentDevice().orientation == .Portrait {
return true
}
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
override func viewDidLoad() {
super.viewDidLoad()
let orientation = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(orientation, forKey: "orientation")
}

As I understand your question you want to know how to get the current device orientation.
Try this...
var orientation = UIDevice.currentDevice().orientation

Related

Force change UINavigationController orientation

How can I force change orientation, when viewWillAppear?
I want only one navigationController to force landscape, other controllers I want to portrait.
When I push to landscape controller it shows like portrait, but when I rotate mobile, it locks, like landscape like I want.
How can I do that, when vieWillAppear? Is there any function to that?
override func viewDidLoad() {
super.viewDidLoad()
let value = UIInterfaceOrientation.landscape.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return .landscape
}
override var shouldAutorotate: Bool {
return true
}

Force one viewcontroller to be only landscape

In my swift project i have all my viewcontroller to only portrait and i want only 1 view controller to be only landscape
My settings here
To do this , you have to set the Settings for both portrait and landscape and all the following code in each view controller except in which you want a landscape view
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
For further help check here

iOS ViewController doesn't layout properly after orientation change

I'm writing an iOS application with some fixed (portrait) views and some orientation dependent views (portrait, lanscape left and landscape right).
The views are contained in a Custom Navigation Controller based on the following code:
class CustomNavigationViewController: UINavigationController {
override func supportedInterfaceOrientations() -> Int {
return self.topViewController.supportedInterfaceOrientations()
}
override func shouldAutorotate() -> Bool {
return self.topViewController.shouldAutorotate()
}
}
I'm implementing supportedInterfaceOrientations() and shouldAutorotate() inside nav child controllers.
Here is a Test Controller
class TestViewController: UIViewController {
var shouldRotate: Bool = false
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
self.shouldRotate = true
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(rotation shouldRotate: Bool) {
self.init(nibName: "TestViewController", bundle: nil)
self.shouldRotate = shouldRotate
}
override func supportedInterfaceOrientations() -> Int {
if shouldRotate == false {
return UIInterfaceOrientation.Portrait.rawValue
} else {
return super.supportedInterfaceOrientations()
}
}
override func shouldAutorotate() -> Bool {
return shouldRotate
}
override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) {
println("from: \(fromInterfaceOrientation.rawValue)")
}
#IBAction func buttonTapped(sender: AnyObject) {
let newvc = TestViewController(rotation: true)
self.navigationController?.pushViewController(newvc, animated: true)
}
}
The first controller is instantiated inside the AppDelegate with rotation: false. The other controllers are created with rotation: true and pushed after tapping the button.
Here is a screenshot of the view:
If I change orientation on the controllers after the first one (the rotable ones) I get the following result:
The controller xib uses autolayout and if I rotate the device before tapping the button it works as expected with the view filling the whole screen.
Also, if I tap the back button while the phone is in landscape the first view is locked in this state:
I'm deploying the app to iOS 8.
How can I make the first view portrait only and the other views correctly layed out after a rotation?
It's probably doesn't matter since it's only printing out a debug message, but don't forget that didRotateFromInterfaceOrientation(_:) was depreciated in iOS 8 with viewWillTransitionToSize(_:withTransitionCoordinator:) taking it's place for responsibilities of a change in view size (which includes rotation).
I think you're on the right track, but instead of overriding both shouldAutorotate() and supportedInterfaceOrientations() only override supportedInterfaceOrientations().
I just did a quick POC to see if it would work. I'm not setting a flag when creating the view controller (and using Swift 2) but you get the idea:
class RotatingViewController: UIViewController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.All
}
}
class FixedViewController: UIViewController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
}
class NavigationController: UINavigationController {
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return self.topViewController?.supportedInterfaceOrientations() ?? UIInterfaceOrientationMask.All
}
}
I think what's happening in your demo is that when you're transitioning to a view controller that is fixed, you're asking it to go into a portrait orientation (which it is) but then not allowing the screen to rotate back to portrait mode.
So.. just try deleting your 'shouldAutorotate()' in your CustomNavigationViewController and see if that works.
Problem is because shouldAutorotate return false.
Your FixedViewController should return shouldAutorotate value true, but supportedInterfaceOrientations should be for example only portrait.
Why do you need it?
When you come back (by using popViewController or dismissViewController) to your FixedViewController (which supports only portrait mode) from another RotateViewController in landscape mode, it should autorotate, to come back to portrait mode

presentedViewController changes orientation of presenting view controller, breaks layout

I have a ViewController A that presents an MPMoviePlayerViewController. I want to force the video player to landscape, so I use this:
In the AppDelegate, supportedInterfaceOrientationsForWindow
if let viewController = self.window!.rootViewController?.presentedViewController {
if let playbackController = viewController as? MPMoviePlayerViewController {
return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
In my video player subclass, I set the supported orientation:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue) | Int(UIInterfaceOrientationMask.LandscapeRight.rawValue)
}
When the video player is closed in landscape, however, View Controller A is stuck in landscape. How do I prevent View Controller A from switching to landscape, and keep it in portrait?
Just add
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
to every view controller that needs it and avoid AppDelegate based orientation support.

Swift UIInterfaceOrientation for Multiple views

I have a navigation controller with multiple views. Most of the views are in portrait, and thus i lock it into portrait view by placing the following code in the Navigation View Controller
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> Int {
return UIInterfaceOrientation.Portrait.toRaw()
}
This works just fine, and locks all my views in portrait orientation. However, This is 1 view that needs to only be in Landscape. If I use the code above, it locks my Landscape View, into portrait mode, and thus cutting off most of the view.
Can anybody help me out with what to use in the Landscape view controller to lock this particular View in landscape only.
I was using this, but it doesn't work.
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.toRaw())
}
override func shouldAutorotate() -> Bool{
// This method is the same for all the three custom ViewController
return true
}
For a small app, the solution I generally use is to have the navigation controller ask the view itself for it's rotation preference:
override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
Then, in each of your view controllers, you can override shouldAutorotate and and supportedInterfaceOrientations to give each controller the behavior you want.
One additional trick, to ensure that your view can rotate back to it's desired rotation, you can use this to to conditionally allow rotation back to portrait:
override func shouldAutorotate() -> Bool {
return !UIInterfaceOrientationIsPortrait(self.interfaceOrientation)
}

Resources