在 iOS 8 中不推荐使用 didRotateFromInterfaceOrientation

Posted

技术标签:

【中文标题】在 iOS 8 中不推荐使用 didRotateFromInterfaceOrientation【英文标题】:didRotateFromInterfaceOrientation is deprecated in iOS 8 【发布时间】:2016-01-13 18:45:27 【问题描述】:

ios 8.0 起,didRotateFromInterfaceOrientation 功能已被弃用,我现在不知道如何正确更改 AVCaptureVideoPreviewLayer 的方向。

根据"interfaceOrientation" is deprecated in iOS 8, How to change this method Objective C,我有以下工作代码来获取基于statusBarOrientationAVCaptureVideoOrientation

- (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;
    

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

[self.videoPreviewLayer.connection setVideoOrientation:[self getOrientation]];

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

尝试 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]];
    ];

但是如果UIViewController 被呈现,这个函数不会被调用(似乎是一个基于"viewWillTransitionToSize:" not called in iOS 9 when the view controller is presented modally 的已知错误)。即使解决了这个错误,还有另一个问题:方向变化等同于尺寸变化。例如,如果一个视图显示为UIModalPresentationFormSheet,如下所示,

SecondViewController *vc = [[SecondViewController alloc] init];
vc.view.backgroundColor = [UIColor greenColor];
vc.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentViewController:vc animated:true completion:nil];

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]];

这是几乎工作,它是如此封闭!问题是,当我收到设备方向更改通知时,可能会启动旋转视图的动画,也可能不会。或者换句话说,如果设备已经倒置旋转但动画仍处于未决状态,则返回值[[UIApplication sharedApplication] statusBarOrientation] 可能不正确。

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

【问题讨论】:

为什么不在“deviceOrientationDidChange”方法中使用UIDeviceOrientation,而不是状态栏方向?只需忽略 .FaceUp 和 .FaceDown 方向。 @almas,感谢您的评论。但问题是设备方向与界面方向并不完全相同。设备可能是上下颠倒的,但视图不支持 .FaceDown。如果我可以保证我当前的视图支持所有四个方向,那么,是的,我认为你的建议在这里是可以的! 好吧,您只需忽略您的应用不支持的所有方向,例如,您可以忽略 FaceUp、FaceDown 和 PortraitUpsideDown。试一试,我相信它会奏效的。 【参考方案1】:

以下内容应该能够在 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
    

【讨论】:

我希望 Apple 能够在幕后实现您的方式。好作品。您仍然可以使用已弃用的didRotate,但您的实现实际上考虑了didRotate 没有的几个极端情况。

以上是关于在 iOS 8 中不推荐使用 didRotateFromInterfaceOrientation的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS9 中不推荐使用 setKeepAliveTimeout

iOS 6 中不推荐使用方向

在 iOS 中不推荐使用 Flutter 依赖项

iOS 中不推荐使用的常量

iOS 7 中不推荐使用音量 [重复]

iOS 8 - 应用程序未正确旋转