Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable rotation only for AVCaptureVideoPreviewLayer

I have a UITabBarController which has 4 items tabs. One of them is an AvCaptureVideoPreviewLayer (is a barcode scanner). What I would like to do is to disable autorotate only for AVCaptureVideoPreviewLayer (like iOS camera app) but not for the item bar which would rotate with the screen. It is a bit difficult situation because I think that the UITabBarConrtoller doesn't allow you easily to disable rotation.

The code for my camera view is:

import UIKit
import AVFoundation

class ScannerViewController: UIViewController, 

// MARK: Properties

/// Manages the data flow from the capture stage through our input devices.
var captureSession: AVCaptureSession!

/// Dispays the data as captured from our input device.
var previewLayer: AVCaptureVideoPreviewLayer!


// MARK: Methods

override func viewDidLoad() {

    super.viewDidLoad()

    view.backgroundColor = UIColor.blackColor()
    self.captureSession = AVCaptureSession()

    // This object represents a physical capture device and the properties associated with that device
    let videoCaptureDevice = AVCaptureDevice.defaultDeviceWithMediaType(AVMediaTypeVideo)
    // Is useful for capturing the data from the input device
    let videoInput: AVCaptureDeviceInput

    do {
        videoInput = try AVCaptureDeviceInput(device: videoCaptureDevice)
    } catch {
        // TODO: maybe show an alert
        return
    }

    if (self.captureSession.canAddInput(videoInput)) {
        self.captureSession.addInput(videoInput)
    } else {
        failed();
        return;
    }

    let metadataOutput = AVCaptureMetadataOutput()

    if (self.captureSession.canAddOutput(metadataOutput)) {
        self.captureSession.addOutput(metadataOutput)

        metadataOutput.setMetadataObjectsDelegate(self, queue: dispatch_get_main_queue())
        metadataOutput.metadataObjectTypes = [AVMetadataObjectTypeEAN8Code, AVMetadataObjectTypeEAN13Code, AVMetadataObjectTypePDF417Code,
            AVMetadataObjectTypeUPCECode, AVMetadataObjectTypeCode39Code,
            AVMetadataObjectTypeCode39Mod43Code, AVMetadataObjectTypeCode93Code,
            AVMetadataObjectTypeCode128Code]
    } else {
        failed()
        return
    }

    // Adds the preview layer to display the captured data. Sets the videoGravity to AspectFill so that it covers the full screen
    self.previewLayer = AVCaptureVideoPreviewLayer(session: self.captureSession);
    self.previewLayer.frame = self.view.layer.bounds;
    self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    self.view.layer.addSublayer(previewLayer);
    self.captureSession.startRunning();

}

override func viewDidLayoutSubviews() {

    self.previewLayer?.frame = self.view.layer.bounds;

}

override func didReceiveMemoryWarning() {

    super.didReceiveMemoryWarning()

}

override func viewWillAppear(animated: Bool) {

    super.viewWillAppear(animated)

    if (self.captureSession.running == false) {
        self.captureSession.startRunning();
    }

}

override func viewWillDisappear(animated: Bool) {

    super.viewWillDisappear(animated)

    if (self.captureSession.running == true) {
        self.captureSession.stopRunning();
    }

}

func failed() {

    let ac = UIAlertController(title: "Scanning not supported", message: "Your device does not support scanning a code from an item. Please use a device with a camera.", preferredStyle: .Alert)
    ac.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
    presentViewController(ac, animated: true, completion: nil)
    self.captureSession = nil

}

func captureOutput(captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [AnyObject]!, fromConnection connection: AVCaptureConnection!) {

    self.captureSession.stopRunning()

    if let metadataObject = metadataObjects.first {
        let readableObject = metadataObject as! AVMetadataMachineReadableCodeObject;

        AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate))
        foundCode(readableObject.stringValue);
    }

}

/// Completes some tasks when a barcode is found.
///
/// - parameter code: The the barcode found.
func foundCode(code: String) {

}

}
like image 705
angeldev Avatar asked Jan 05 '16 10:01

angeldev


1 Answers

I'm not 100% sure if I understand it correctly. But what you could do is:

1 - Subclass your UITabBarController and override shouldAutorotate with something like this:

override var shouldAutorotate: Bool {
    guard let viewController = tabBarController?.selectedViewController else { return false }
    return viewController.shouldAutorotate
}

This means that the selected UIViewController will define if it should autorotate.

2 - Now that the UITabBarController will ask its ViewControllers if it should autorotate, you have to override shouldAutorotate in every controller as well.

And that's it!

Sorry if I misunderstood your question. If you provide more information it would help.

Take care :)

like image 73
Gabriel Oliva Avatar answered Nov 13 '22 19:11

Gabriel Oliva