5

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")
    }
}
weegee
  • 3,256
  • 2
  • 18
  • 32
Spiderixx
  • 65
  • 6
  • What i did was in `UIApplicationDelegate` . declare two variables `var shouldSupportAllOrientation = true` and `var orientationLock = UIInterfaceOrientationMask.portrait` and using supportedInterfaceOrientationsFor in appDelegate return the orientationLock variable. in your viewcontroller `appDelegate?.shouldSupportAllOrientation = true` `appDelegate?.orientationLock = .portrait` – Kamal Upasena Jul 09 '19 at 10:14
  • @KamalUpasena I just tried that and it sadly does not work. I did it likewise: in my AppDelegate I made the two variables as you specified. Then in my view controller under viewWillAppear (also tried viewDidLoad) I used it as you do, and the view still rotates regardless of the extra code. – Spiderixx Jul 09 '19 at 11:04
  • Add Orientation support for 4 items in info.plist – Kamal Upasena Jul 09 '19 at 12:13
  • @KamalUpasena can you elaborate? I am not sure I understand what these 4 items are. – Spiderixx Jul 09 '19 at 12:17
  • Add Device Orientation as Portrait, Upside Down, Landscape Left, Landscape Right from the General -> Deployment Info – Kamal Upasena Jul 09 '19 at 12:21
  • Ah, that I have already checked for all Device Orientations. The issue is related to the ViewController in which i display my image rotates regardless of what I have tried. – Spiderixx Jul 09 '19 at 12:25

1 Answers1

1

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)
Spiderixx
  • 65
  • 6
Vinu Jacob
  • 393
  • 2
  • 15
  • Hey. I have tried your solution and sadly it does not work for my case. There are no errors or anything. It simply rotates regardless of the code. – Spiderixx Jul 25 '19 at 11:00
  • in my case, it is working fine. Which is device OS version. – Vinu Jacob Jul 25 '19 at 11:46
  • It is an iPad pro, version 12.3.1. – Spiderixx Jul 25 '19 at 12:28
  • it is working correctly in iPhone 8 12.3.1. I update the answer. Please check that. Call that function inside **viewDidload()** – Vinu Jacob Jul 25 '19 at 12:41
  • 1
    Hmm, no luck for me yet. I think there might be some setup configuration which is causing this issue. I tried your solution on a test app and it works. I will mark it as correct answer. – Spiderixx Jul 26 '19 at 11:33