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) {
}
}
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 :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With