AVCaptureVideoPreviewLayer在禁用UI旋转时方向错误

11

我在视图控制器的视图层次结构中添加了一个AVCaptureVideoPreviewLayer实例。

- (void) loadView {
   ...

   self.previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:nil];
   self.previewLayer.frame = self.view.bounds;
   self.previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;

   [self.view.layer addSublayer: _previewLayer];

   // adding other UI elements
   ...
}

...

- (void) _setupPreviewLayerWithSession: (AVCaptureSession*) captureSession
{
   self.previewLayer.session = self.captureManager.captureSession;
   self.previewLayer.connection.videoOrientation = AVCaptureVideoOrientationLandscapeRight;
}
层框架在 -viewDidLayoutSubviews 方法中更新。视图控制器方向被锁定为 UIInterfaceOrientationMaskLandscapeRight
问题如下:
  1. 设备处于横屏方向
  2. 以模态方式呈现视图控制器 - 视频层显示正确。 Correct orientation
  3. 然后锁定设备,同时将其旋转到纵向方向。
  4. 然后解锁设备,仍处于纵向方向,并且视频层会显示旋转了90度的状态。但是,视频层的框架是正确的。所有其他用户界面元素都会正确地显示。几秒钟后,该层会自动进行正确的旋转。 请查看以下层和用户界面元素的边界 Incorrect orientation

我尝试了以下方法来更新视频层方向(没有效果):

  • 订阅 AVCaptureSessionDidStartRunningNotificationUIApplicationDidBecomeActiveNotification 通知
  • 在调用 -viewWillTransitionToSize:withTransitionCoordinator: 方法时更新
  • -viewWillAppear:

问题似乎与视频层方向本身无关,而更多地与视图层次结构布局有关。

UPDATE:

如建议的那样,我也尝试在设备方向更改时更新视频层方向,但没有帮助。

我还注意到,该问题主要发生在应用程序启动并首次呈现屏幕后。在同一会话期间的后续屏幕呈现中,该问题的再现率非常低(大约为1/20)。


1
在viewWillAppear方法和enterForeground事件中注册进入前台通知,添加func fixOrientation()函数调用。在该函数中使用以下代码:UIDevice.current.setValue(NSNumber(value: UIInterfaceOrientation.portrait.rawValue), forKey: "orientation")你需要确定它是横向左/右方向。我几年前在Obj-C中使用过这段代码,现在只作为注释,未经测试。 - Sean Lintern
1个回答

3

尝试这段代码:

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(orientationChanged:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
-(void)orientationChanged:(NSNotification *)notif {

    [_videoPreviewLayer setFrame:_viewPreview.layer.bounds];
    if (_videoPreviewLayer.connection.supportsVideoOrientation) {
        _videoPreviewLayer.connection.videoOrientation = [self interfaceOrientationToVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
    }

}

- (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 (%d)",orientation);
    return AVCaptureVideoOrientationPortrait;
}

谢谢,我已经尝试了您的建议,但仍然没有帮助。请查看问题的更新部分以获取更多信息。 - NikGreen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接