iOS设备快速旋转180度会导致摄像头倒置
我已经实现了下面的代码,以基于iOS设备快速旋转180度会导致摄像头倒置,ios,objective-c,uiinterfaceorientation,avcapturesession,viewdidlayoutsubviews,Ios,Objective C,Uiinterfaceorientation,Avcapturesession,Viewdidlayoutsubviews,我已经实现了下面的代码,以基于UIInterfaceOrientation更改AVCaptureVideoSession的方向: - (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation:(UIInterfaceOrientation)orientation { switch (orientation) { case UIInterfaceOrientationPortrait:
UIInterfaceOrientation
更改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度,相机将倒置显示
以下是旋转前摄影机视图的外观:
这是旋转后的样子:
此外,下面是我的viewdilayoutsubviews
的实现:
- (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度旋转时相机视图会颠倒吗?我相信这是因为当视图从纵向更改为向上时,
viewdilayoutsubviews
不会被调用。当你旋转得很快时,它会从一个直线转到另一个直线。如果旋转速度缓慢,它将穿过横向方向,因此会调用viewdilayoutsubviews
,然后调用您的方法
我建议您使用方向改变时调用的方法之一。我知道苹果建议越来越少地使用它们,因为它们希望在大小改变时视图也会改变,但也有一些情况,比如,当你真的需要知道方向改变时
例如,您可以注册以接收此通知:
UIApplicationIDChangeStatusBaroOrientationNotification
在此之前,我遇到了相同的问题,解决了我的问题
我声明了一个全局变量:
@interface YourViewController ()
{
...
UIDevice *iOSDevice;
}
..
@end
在实现(.m文件)下,我在-视图下声明了NSNotification observer,如下所示:
@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];
}
我创建了一个函数,返回复制的当前设备的方向,如:
在我的-InterfaceOrientationVideoOrientation
方法中获取一个战利品,它将iOSDevice.orientation
转换为AVCaptureVideoOrientation
与您的相同
(在我的例子中,我需要下面的这些函数,但出于某种原因,请看一下它可能对您有用)
编辑
对于默认方向:您需要检查“当前”方向
- (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
在触发之前,先确定要旋转的设备
希望这对你有帮助 我在Apple tools中看到过这一点,所以我不确定这是不是你的bug。@PaulCezanne啊,真有趣!哪一个?我只是想在camera应用程序上复制它,但没能做到。我在camera和消息中看到过它,但也许我是通过消息启动camera的。我想不起来了。我也认为这在iOS8.0中发生得更多,我不记得最近从相机上看到过,但我确实在8.3中看到了从消息启动相机时的旋转奇怪现象。@PaulCezanne Weird…我只是尝试通过从消息启动相机来测试,但也没有看到。我以前也有过同样的问题,我提出的解决方案是添加NSNotificationCenter,当通知直接以通知所针对的方法触发时,更改previewLayer
的方向。。我现在不能给你一个密码这里太晚了我的密码在办公室里。。嗯……我明白了,那是有道理的。因此,您建议将我当前拥有的代码放入viewdilayoutsubviews
中,类似于-(void)orientationChanged:(NSNotification*)通知
或adjustViewsForOrientation
,对吗?我想您只需要将最后一个if
放入orientationChanged:
。处理视图大小调整的其余代码很好地放在了viewdilayoutsubviews
中。我不认为每次调用该方法时都应该添加该子层。这也是有意义的。您认为在哪里添加子层更合适?(很抱歉提出这些问题,这已经伤了我的头一段时间了,哈哈)。您可能可以检查它是否有超层
,只有在没有的情况下才添加它。对于Swift 3.0-NotificationCenter.default.addObserver(self,selector:#selector(deviceRotated)(通知:),名称:NSNotification.name.uiApplicationIDChangeStatusBarOrientation,对象:。无)这几乎可以完美地工作!我现在唯一的问题是,如果我在iPad上运行应用程序并以横向模式启动,相机视图将以横向模式显示。如果我将设备旋转到纵向,然后再旋转回横向,相机将正确显示。@narner,关于这一点,您需要检查-viewDidLoad
内的方向。。对于默认设置。。对不起,我没有把这个包括在这里。。我以为你已经有了那一个…这是有道理的。那么,像“previewLayer.connection.videoOrientation=[[UIDevice currentDevice]orientation];”?不完全需要-interface-orientation-videoorientation
方法中转换的方向。。我将尝试编辑我的答案:)@纳纳:好了,试试看……)
- (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
}