如何在没有 [UI 设备 setValue:forKey:@"orientation"] 的情况下更改 UI 方向

How to change UI orientation without [UIDevice setValue:forKey:@"orientation"]

我的目标是使用按钮改变 lock/unlock 方向。在锁定模式下,方向可以通过按钮切换,在解锁模式下,方向由传感器确定。
我试图用 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"] 来实现这个,但是这段代码有问题。
假设目前我的应用是 'Lock mode, portrait UI, portrait device'。然后我将设备旋转到左侧横向,并解锁方向。我预计 [[UIDevice currentDevice] orientation] 应该是 UIDeviceOrientationLandscapeLeft。但是这个值是 UIDeviceOrientationPortrait 虽然真实的设备是横向的!

我也尝试使用下面的代码通知中心。

[[NSNotificationCenter defaultCenter]  
           addObserver:self  
              selector:@selector(onDeviceOrientationChanged:)  
                  name:UIDeviceOrientationDidChangeNotification  
                object:nil];

但是这段代码不能正常工作。如果设备处于横向并且 UI 方向由 [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIDeviceOrientationPortrait] 设置为纵向,则当我将设备旋转为纵向时 onDeviceOrientationChanged 不会被调用。我认为设备的方向值已经设置为纵向(通过我的代码,而不是传感器)。

ps。当然,我勾选了 Required full screen 选项。

编辑:知道如何获得不受[[UIDevice currentDevice] setValue]影响的设备的真实方向也是一个很好的答案。

我使用 MotionManager 解决了这个问题。当我锁定(或更改)方向时,[[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation] forKey:@"orientation"] 就足够了。
但是,当我解锁方向时,我使用 MotionManager 和以下代码刷新了方向。

CMMotionManager motionManager = [[CMMotionManager alloc] init];

[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
    withHandler:^(CMAccelerometerData * _Nullable accelerometerData, NSError * _Nullable error) {
        [motionManager stopAccelerometerUpdates];

        CMAcceleration acceleration = accelerometerData.acceleration;
        UIInterfaceOrientation orientation;
        if (acceleration.x >= 0.75) {
            orientation = UIInterfaceOrientationLandscapeLeft;
        } else if (acceleration.x <= -0.75) {
            orientation = UIInterfaceOrientationLandscapeRight;
        } else if (acceleration.y <= -0.75) {
            orientation = UIInterfaceOrientationPortrait;
        } else if (acceleration.y >= 0.75) {
            orientation = UIInterfaceOrientationPortraitUpsideDown;
        } else {
            return;
        }
        [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:orientation]
                            forKey:@"orientation"];
        [UINavigationController attemptRotationToDeviceOrientation];
    }];

当然,您应该了解 supportedInterfaceOrientationsshouldAutorotate 方法。