Быстрый поворот устройства iOS на 180 градусов приводит к перевернутому просмотру камеры.
Я реализовал код ниже, чтобы изменить ориентацию AVCaptureVideoSession
на основе UIInterfaceOrientation
:
- (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 градусов, камера будет показана вверх ногами.
Вот как выглядит вид камеры перед вращением:
И вот как это выглядит после вращения:
Кроме того, вот мой реализация viewDidLayoutSubviews
:
- (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 градусов?
2 ответа:
У меня была та же проблема до этого, что решило мою проблему.
Я объявил глобальную переменную:
@interface YourViewController () { ... UIDevice *iOSDevice; } .. @end
Под
implementation
(.m file) я объявил nsnotification observer под-viewWillAppear
как:@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]; }
Я сделал функцию, которая возвращает ориентацию скопированного текущего устройства, как:
Возьмите бабло у моего метода
-interfaceOrientationToVideoOrientation
, он преобразуетiOSDevice.orientation
вAVCaptureVideoOrientation
то же самое, что у вас есть..
(в моем случае мне нужна была эта функция ниже, но взгляните на нее может быть вам полезно по какой-то причине)
- (AVCaptureVideoOrientation)interfaceOrientationToVideoOrientation { switch (iOSDevice.orientation) { case UIInterfaceOrientationPortraitUpsideDown: return AVCaptureVideoOrientationPortraitUpsideDown; case UIInterfaceOrientationLandscapeLeft: return AVCaptureVideoOrientationLandscapeLeft; case UIInterfaceOrientationLandscapeRight: return AVCaptureVideoOrientationLandscapeRight; default: case UIDeviceOrientationPortrait: return AVCaptureVideoOrientationPortrait; } } - (AVCaptureConnection *)setAutoVideoConnectionOrientation:(BOOL)status { AVCaptureConnection *videoConnection = nil; //This is for me //for (AVCaptureConnection *connection in stillImageOutput.connections) { //This might be for you for (AVCaptureConnection *connection in previewLayer.connection) { for (AVCaptureInputPort *port in [connection inputPorts]) { if ([[port mediaType] isEqual:AVMediaTypeVideo]) { videoConnection = connection; if (status == YES) { [videoConnection setVideoOrientation:[self interfaceOrientationToVideoOrientation]]; } else { [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait]; } } if (videoConnection) { break; } } } return videoConnection; }
Edit
Для ориентации по умолчанию: вам нужно проверить" текущую " ориентацию.
- (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 советует использовать их все меньше и меньше, потому что они хотят, чтобы представления менялись, когда размер изменения, но бывают случаи, как этот, когда вам действительно нужно знать, что ориентация изменилась.viewDidLayoutSubviews
не вызывается, когда вид меняется с портретной ориентации на перевернутую. Когда вы вращаетесь очень быстро, он переходит от одного к другому прямо. Если вы медленно вращаетесь, он проходит через ландшафтную ориентацию, и поэтомуviewDidLayoutSubviews
вызывается, а затем ваш метод.Например, вы можете зарегистрироваться, чтобы получать такие уведомления:
UIApplicationDidChangeStatusBarOrientationNotification