Quick 180 rotation of iOS Device results in the camera viewing upside-down

后端 未结 2 869
囚心锁ツ
囚心锁ツ 2021-02-14 05:10

I\'ve implemented the code below to change the orientation of an AVCaptureVideoSession based upon the UIInterfaceOrientation:

- (AVCapt         


        
相关标签:
2条回答
  • 2021-02-14 06:09

    I believe it's happening because viewDidLayoutSubviews doesn't get called when the view changes from Portrait orientation to UpsideDown. When you rotate very quickly it goes from one to another straight. If you rotates slowly it pass through a Landscape orientation and so viewDidLayoutSubviews gets called and subsequently your method.

    I advise you to use one of the methods that get called when orientation changes. I know Apple advise to use them less and less because they want views to change when size changes, but there are cases, like this one when you really need to know that the orientation changed.

    For example you could register to receive this notifications: UIApplicationDidChangeStatusBarOrientationNotification

    0 讨论(0)
  • 2021-02-14 06:11

    I had the same issue before here what solved my issue.

    I declared a global variable:

    @interface YourViewController ()
    {
        ...
        UIDevice *iOSDevice;
    }
    
    ..
    
    @end
    

    Under implementation (.m file) i declared NSNotification observer under -viewWillAppear like:

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

    I made a function that returns the orientation of the copied current device like:

    Take a loot at my -interfaceOrientationToVideoOrientation method, it converts the iOSDevice.orientation into AVCaptureVideoOrientation same with what you have there..


    (In my case i needed this functions below, but take a look at it might be useful to you for some reason)

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

    For default orientation: You need to check the "current" orientation.

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

    Note:

    Using NSNotificationCenter let the rotation of the device to be settled first before triggered..

    Hope this have help you..

    0 讨论(0)
提交回复
热议问题