I have an issue about the orientation on iPad.
I disabled the orientation on iPhone but i can change it programmatically on some specific controller.
But on iPad i can’t. i don’t know why although i searched in this website and some developers write answers to check UIRequiresFullScreene and i do it.
But it disables the orientation on all screens.
Is there any way to give ability to change orientation on specific controller on iPad ?
The following code i used to change iPad Orientation but it is not working.
UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
Thanks advance
When you set programmatically the orientation of the device. To perform the orientation animation the function
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
from AppDelegate is being called.
If you have set it there to return only UIInterfaceOrientationMask.portrait you will never see the transition.
Also I personally have these kind of problems and to solve this I had to programmaticaly force the phone to rotate to the current Orientation and then to rotate to the wanted orientation.
Example for phone to rotate landscapeLeft from portrait
func setOrientationToLandScapeOnly() {
appDelegate.shouldForceLandscapeOnly = true
appDelegate.shouldForcePortraitOnly = false
if UIDevice.current.userInterfaceIdiom == .phone {
switch UIApplication.shared.statusBarOrientation {
case .landscapeLeft, .landscapeRight:
return
default:
APIOrientationHandler.shared.setDeviceValueForOrientation(UIInterfaceOrientation.portrait.rawValue)
APIOrientationHandler.shared.setDeviceValueForOrientation(UIInterfaceOrientation.landscapeLeft.rawValue)
return
}
}
}
And inside AppDelegate.swift
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if shouldForcePortraitOnly {
return UIInterfaceOrientationMask.portrait
}
if shouldForceLandscapeOnly {
return UIInterfaceOrientationMask.landscape
}
if (UIDevice.current.userInterfaceIdiom == UIUserInterfaceIdiom.pad) {
return UIInterfaceOrientationMask.landscape
}
return UIInterfaceOrientationMask.portrait
}
Related
I want to allow user to record a video only in portrait mode(orientation) and restrict the user to record in landscape. I'm using UIImagePickerController and I couldn't find any orientation options in it. could anyone help me out in this?
Write below code in AppDelegate:
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
guard let mainController = navigationController else { return UIInterfaceOrientationMask.all }
if ((mainController.visibleViewController as? CameraVC) != nil) == false {
//This VC should support only Portrait Mode.
return UIInterfaceOrientationMask.portrait
} else {
//Else support All Modes.
return UIInterfaceOrientationMask.all
}
}
And It will Restrict Your "CameraVC" to Rotate in landscape Mode.
Background
I have an app that uses AVFoundation in order to have a custom camera. This happens in the OCRViewController. When I take a picture I send the captured picture to a different view ImagePreviewViewController.
I am using Xcode 10.2.1 (10E1001) with Swift 5
The Goal
What I would like to achieve is to lock the orientation of the ImagePreviewViewController to the original orientation of the image. I already know how to get the orientation of the image but I am not able to lock the orientation of the view.
I get the image rotation as such: let imageOri = capturedImage?.imageOrientation
What did I try?
I tried the accepted answers at and several other sources:
How to lock orientation just for one view controller?
How to lock orientation of one view controller to portrait mode only in Swift
https://www.hackingwithswift.com/example-code/uikit/how-to-lock-a-view-controllers-orientation-using-supportedinterfaceorientations
Reading the documentation at https://developer.apple.com/documentation/uikit/uiviewcontroller#//apple_ref/occ/instm/UIViewController/supportedInterfaceOrientations under Handling View Rotation the following is stated:
I also tried the many suggested solutions while writing this query, however, the majority appears to use the following approach (or a variation of it), and it does not work for me.
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
override func shouldAutorotate() -> Bool{
return false
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.Portrait
}
As of iOS 8, all rotation-related methods are deprecated. Instead, rotations are treated as a change in the size of the view controller’s view and are therefore reported using the viewWillTransition(to:with:) method.
However, I am not sure how to progress from here.
Interesting code snippets
The following method is in my OCRViewController, here I instantiate the ImagePreviewViewController and attach the captured image.
func displayCapturedPhoto(capturedPhoto : UIImage) {
let imagePreviewViewController = storyboard?.instantiateViewController(withIdentifier: "ImagePreviewViewController") as! ImagePreviewViewController
imagePreviewViewController.capturedImage = capturedPhoto
navigationController?.pushViewController(imagePreviewViewController, animated: true)
}
Using the below override function inside my ImagePreviewViewController I am able to detect the orientation of the view controller.
override func viewDidAppear(_ animated: Bool) {
if UIDevice.current.orientation.isLandscape {
print("Landscape")
} else {
print("Portrait")
}
}
To restrict the rotation of one screen, use this.
In AppDelegate
var restrictRotation = Bool()
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
if !restrictRotation {
return .portrait
} else {
return .all
}
}
In your viewcontroller add the function,
func restrictRotation(restrict : Bool) -> Void {
let appDelegate = UIApplication.shared.delegate as? AppDelegate
appDelegate?.restrictRotation = restrict
}
In the ViewDidload() method, call the function to disable rotation.
self.restrictRotation(restrict: false)
in viewWillDisappear() method, call the function to enable rotation.
self.restrictRotation(restrict: true)
I'm developing an app with Xcode9 using Swift4 and it was originally intended for just iPads but now needs to run on phones too. I need to lock the phones to Portrait and iPads remain Portrait/Landscape.
I've done this before using the shouldautorotate function and returning true or false depending on the device as below.
override func shouldAutorotate() -> Bool {
return false
}
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.all
}
However, when I change the orientation it does not fire. Is this another depreciated method and if so how do I restrict the orientation now?
If your view controller is embedded into UINavigationController or UITabBarController, then this shouldAutorotate() is queried from them as this container is the topmost view controller. And after iOS updates it does not ask for contaning view controllers if they need to be rotated or not. Thus you may use your custom subclass and creat it in runtime or provide as custom calss in your storyboard:
import UIKit
class CustomNavigationController: UINavigationController {
override var shouldAutorotate: Bool {
return self.viewControllers.last?.shouldAutorotate ?? true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return self.viewControllers.last?.supportedInterfaceOrientations ?? .all
}
}
After much googling, this worked for me
https://stackoverflow.com/questions/38969419/ios-how-can-enable-or-disable-rotate-on-each-uiviewcontroller
I'm working on an universal iOS app and I'm using SplitViewController. I have been trying to disable the splitView on iPhone 6+ and 6s+ in landscape mode but nothing seems to work. I attempted to override the UITraitCollection by setting its horizontalSizeClass to Compact, it doesn't seem to work either. Has anyone attempted this? Below is my code to override UITraitCollection
override func overrideTraitCollectionForChildViewController(childViewController: UIViewController) -> UITraitCollection? {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
let collections = [UITraitCollection(horizontalSizeClass: .Compact), UITraitCollection(verticalSizeClass: .Compact) ]
return UITraitCollection(traitsFromCollections: collections)
}else {
return super.traitCollection
}
}
I have this in my viewDidLoad of the splitViewController.
I'm trying to show different orientation depending on device.
On iPhone I want to allow portrait orientation, on iPad I want to allow landscapeleft orientation.
Is that possible?
I tried
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
else {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
}
The code you posted does the job. However you need to add Supported Device Orientations to Info.plist. The easiest way to do this is to select appriopriate settings in Project->Target->Summary->Supported Device Orientations section.
Add this to your app delegate: (Swift)
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
} else {
return Int(UIInterfaceOrientationMask.LandscapeLeft.rawValue | UIInterfaceOrientationMask.LandscapeRight.rawValue)
}
}