iOS设备快速旋转180°会导致相机颠倒

我已经实现了下面的代码来改变基于AVCaptureVideoSession的方向:

 - (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:(UIInterfaceOrientation)orientation { switch (orientation) { case UIInterfaceOrientationPortrait: return AVCaptureVideoOrientationPortrait; case UIInterfaceOrientationPortraitUpsideDown: return AVCaptureVideoOrientationPortraitUpsideDown; case UIInterfaceOrientationLandscapeLeft: return AVCaptureVideoOrientationLandscapeLeft; case UIInterfaceOrientationLandscapeRight: return AVCaptureVideoOrientationLandscapeRight; default: break; } NSLog(@"Warning - Didn't recognise interface orientation (%ld)",(long)orientation); return AVCaptureVideoOrientationPortrait; } 

这个代码几乎完美的工作。 但是,发生的一个问题是,如果您快速旋转iOS设备180度,相机将显示颠倒。

以下是相机视图在旋转之前的样子:

在这里输入图像说明

轮换之后的样子如下所示:

在这里输入图像说明

另外,这里是我的viewDidLayoutSubviews实现:

 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; previewLayer.frame = self.view.bounds; self.view.translatesAutoresizingMaskIntoConstraints = NO; previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; [self.view.layer addSublayer:previewLayer]; if (previewLayer.connection.supportsVideoOrientation) { previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation]; } } 

有没有人有一个想法,当这个180度的旋转发生时,为什么相机视图会颠倒?

在这之前我有同样的问题解决了我的问题。

我宣布了一个全局variables:

 @interface YourViewController () { ... UIDevice *iOSDevice; } .. @end 

implementation (.m文件)我宣布NSNotification观察员在-viewWillAppear像:

 @implementation YourViewController -(void)viewWillAppear:(BOOL)animated { [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationChanged:) name:UIDeviceOrientationDidChangeNotification object:[UIDevice currentDevice]]; } -(void)viewWillDisappear:(BOOL)animated { [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; } - (void)orientationChanged:(NSNotification *)notification { iOSDevice = notification.object; previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation]; //or [self setAutoVideoConnectionOrientation:YES]; } 

我做了一个函数,返回复制的当前设备的方向,如:

在我的iOSDevice.orientation方法采取掠夺,它将iOSDevice.orientation转换为AVCaptureVideoOrientation与您在那里相同。


(在我的情况下,我需要下面的这个function,但看看它可能是有用的,你出于某种原因)

 - (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation { switch (iOSDevice.orientation) { case UIInterfaceOrientationPortraitUpsideDown: return AVCaptureVideoOrientationPortraitUpsideDown; case UIInterfaceOrientationLandscapeLeft: return AVCaptureVideoOrientationLandscapeLeft; case UIInterfaceOrientationLandscapeRight: return AVCaptureVideoOrientationLandscapeRight; default: case UIDeviceOrientationPortrait: return AVCaptureVideoOrientationPortrait; } } - (AVCaptureConnection *)setAutoVideoConnectionOrientation:(BOOL)status { AVCaptureConnection *videoConnection = nil; //This is for me //for (AVCaptureConnection *connection in stillImageOutput.connections) { //This might be for you for (AVCaptureConnection *connection in previewLayer.connection) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([[port mediaType] isEqual:AVMediaTypeVideo]) { videoConnection = connection; if (status == YES) { [videoConnection setVideoOrientation:[self interfaceOrientationToVideoOrientation]]; } else { [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; } } if (videoConnection) { break; } } } return videoConnection; } 

编辑

对于默认方向:您需要检查“当前”方向。

 - (void)viewDidLoad { [super viewDidLoad]; // assuming you finish setting the `previewLayer` .. // after all of that code, when the view is ready for displaying // if you implemented this approach the best thing to do is: // set this iOSDevice = [UIDevice currentDevice]; // then call previewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation]; // to update the `previewLayer.connection.videoOrientation ` for default orientation } 

注意:

使用NSNotificationCenter让设备的旋转在触发之前先被解决。

希望这有助于你..

我相信这是因为viewDidLayoutSubviews在视图从纵向变为UpsideDown时不会被调用。 当你很快旋转时,它会从一个直线到另一个直线。 如果缓慢旋转,则会通过横向方向,因此将调用viewDidLayoutSubviews ,随后调用您的方法。

我build议你使用方向改变时调用的方法之一。 我知道苹果build议使用它们的次数越来越less,因为他们希望视图在大小改变时发生改变,但是有些情况下,比如当你真的需要知道改变方向时。

例如,您可以注册以接收此通知: UIApplicationDidChangeStatusBarOrientationNotification