在 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,我有以下工作代码来获取基于statusBarOrientation
的AVCaptureVideoOrientation
:
- (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的主要内容,如果未能解决你的问题,请参考以下文章