didRotateFromInterfaceOrientation 在 iOS 8 中已弃用

Yuc*_*ong 5 objective-c ios ios8

从 iOS 8.0 开始,该功能已被弃用,我现在不知道如何正确更改AVCaptureVideoPreviewLayerdidRotateFromInterfaceOrientation的方向。

根据“interfaceOrientation”在 iOS 8 中已弃用,如何更改此方法 Objective C,我有以下工作代码来获取AVCaptureVideoOrientation基于statusBarOrientation

- (AVCaptureVideoOrientation)getOrientation {
    // Translate the orientation
    switch ([[UIApplication sharedApplication] statusBarOrientation]) {
        case UIInterfaceOrientationPortrait:
            return AVCaptureVideoOrientationPortrait;
        case UIInterfaceOrientationPortraitUpsideDown:
            return AVCaptureVideoOrientationPortraitUpsideDown;
        case UIInterfaceOrientationLandscapeLeft:
            return AVCaptureVideoOrientationLandscapeLeft;
        case UIInterfaceOrientationLandscapeRight:
            return AVCaptureVideoOrientationLandscapeRight;
        default:
            return AVCaptureVideoOrientationPortrait;
    }
}
Run Code Online (Sandbox Code Playgroud)

当方向改变时,我需要调用以下函数:

[self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];
Run Code Online (Sandbox Code Playgroud)

但我不知道该把它放在哪里合适。

尝试1

由于didRotateFromInterfaceOrientation已弃用并且 Apple 建议使用viewWillTransitionToSize:withTransitionCoordinator:,因此尝试这似乎很自然:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext>  _Nonnull context) {
        [self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];
    }];
}
Run Code Online (Sandbox Code Playgroud)

但如果正在呈现,则不会调用此函数UIViewController(似乎是一个基于“viewWillTransitionToSize:”的已知错误,当​​视图控制器以模态方式呈现时,在 iOS 9 中不会调用)。即使这个错误得到解决,还有另一个问题:方向改变并不等于尺寸改变。例如,如果视图呈现UIModalPresentationFormSheet如下:

SecondViewController *vc = [[SecondViewController alloc] init];
vc.view.backgroundColor = [UIColor greenColor];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:vc animated:true completion:nil];
Run Code Online (Sandbox Code Playgroud)

iPad 的横向和纵向模式下呈现的视图尺寸相同:

因此,我不能简单地使用viewWillTransitionToSize.

尝试2

我注意到这UIDeviceOrientationDidChangeNotification并没有被弃用。伟大的!我尝试注册一个通知:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Some other code to set up the preview layer 
    // ...

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(deviceOrientationDidChange:)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

- (void)deviceOrientationDidChange:(NSNotification *)notification {
    [self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];
}
Run Code Online (Sandbox Code Playgroud)

几乎可以工作了,而且已经关闭了!问题是,当我收到设备方向更改通知时,旋转视图的动画可能会启动,也可能不会。或者换句话说,[[UIApplication sharedApplication] statusBarOrientation]如果设备已经上下旋转但动画仍处于待处理状态,则返回值可能不正确。

我不知道还能尝试什么:( 有什么想法吗?

Yuc*_*ong 4

以下应该能够在 swift 2.1 中正确处理视频预览的方向:

override func viewWillAppear(animated: Bool) {
    super.viewDidLoad()

    NSNotificationCenter.defaultCenter().addObserver(self,
        selector: Selector("deviceOrientationDidChange:"),
        name: UIDeviceOrientationDidChangeNotification,
        object: nil)
}

override func viewDidDisappear(animated: Bool) {
    NSNotificationCenter.defaultCenter().removeObserver(self)
    super.viewDidDisappear(animated)
}

func deviceOrientationDidChange(sender: AnyObject) {
    let deviceOrientation = UIDevice.currentDevice().orientation;
    switch (deviceOrientation)
    {
    case .Portrait:
       previewLayer.connection.videoOrientation = .Portrait
    case .LandscapeLeft:
       previewLayer.connection.videoOrientation = .LandscapeRight
    case .LandscapeRight:
        previewLayer.connection.videoOrientation = .LandscapeLeft
    case .PortraitUpsideDown:
       previewLayer.connection.videoOrientation = .PortraitUpsideDown
    default:
        break
    }
}
Run Code Online (Sandbox Code Playgroud)