强制设备旋转使用 +attemptRotationToDeviceOrientation 失败

9
根据此处的UIViewController文档,

https://developer.apple.com/library/ios/documentation/uikit/reference/UIViewController_Class/Reference/Reference.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

使用[UIViewController attemptRotationToDeviceOrientation]会强制系统尝试将界面旋转到新的方向。我正在尝试通过以下方式从竖屏强制旋转为横屏:

  • 在尝试旋转之前设置forceLandscape标志
  • 调用[UIViewController attemptRotationToDeviceOrientation]
  • 在我的视图控制器中实现-supportedInterfaceOrientations并检查一个标志以更改支持的方向,例如

这将强制再次调用-supportedInterfaceOrientations,看起来像是

- (NSUInteger)supportedInterfaceOrientations {
    return self.forceLandscape ? UIInterfaceOrientationMaskLandscapeLeft : UIInterfaceOrientationMaskPortrait;
}

尽管-supportedInterfaceOrientations被调用并返回新的方向,但接口不会旋转。我已确认该项目允许所有方向,并且此视图控制器是窗口的根视图控制器。是否有其他人遇到过这个问题并找到解决方案?我知道所有修复此问题的技巧(呈现和解除模态等),但如果可能的话,我希望有一个清晰的解决方案。我已在iOS 6和7上验证了此问题。
以下是完整的代码以进行复制:
@interface ALTViewController ()
@property (nonatomic, assign) BOOL forceLandscape;
@end

@implementation ALTViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

        self.forceLandscape = NO;
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setTitle:@"button" forState:UIControlStateNormal];
    [button sizeToFit];
    [self.view addSubview:button];
    button.center = self.view.center;
    [button addTarget:self
               action:@selector(buttonPressed:)
     forControlEvents:UIControlEventTouchUpInside];
}

- (void)buttonPressed:(id)sender
{
    self.forceLandscape = YES;
    [UIViewController attemptRotationToDeviceOrientation];
}

- (NSUInteger)supportedInterfaceOrientations
{
    return self.forceLandscape ? UIInterfaceOrientationMaskLandscapeLeft : UIInterfaceOrientationMaskPortrait;
}

在你的问题中,你似乎混淆了设备和接口这两个术语,这使得人们很难理解你想要实现什么。你是想即使设备保持相同的方向,也要将接口旋转到新的方向吗? - Till
好的 - 我同意 :) 我刚刚编辑了问题以便更清晰。你说得对,我正在尝试在设备保持竖屏方向的情况下强制接口为横屏方向。 - alexshafran
2个回答

12
调用 attemptRotationToDeviceOrientation 只有在设备自身旋转时,才会旋转界面的方向。举例来说,如果您的视图控制器仅支持纵向方向,并且用户将设备旋转到横向方向,则不会发生界面旋转。当设备处于横向方向时,假设您的代码切换一个标志以允许横向方向。接下来,界面方向会发生什么变化呢?因为设备方向已经发生了,所以不会有任何变化。如果要使界面方向与设备方向相匹配,则需要调用 attemptRotationToDeviceOrientation。
在我的代码中,我最近创建了一个自定义的多部分视图动画,如果在其中发生界面旋转,它就不会看起来正确。因此,在短暂的动画期间,我关闭了界面旋转选项。如果用户在动画期间旋转设备,则不会发生界面方向变化。但是,当重新打开界面方向时,直到我调用 attemptRotationToDeviceOrientation 时,界面才会旋转以匹配设备方向。

2
我开始同意你的观点。然而,文档表明我们可以根据应用程序特定条件更改支持的接口: “一些视图控制器可能希望使用应用程序特定条件来确定支持哪些界面方向。如果您的视图控制器这样做了,当这些条件发生变化时,您的应用程序应该调用此类方法。系统会立即尝试旋转到新的方向。” - alexshafran
3
我在这里提出了一个类似的问题https://dev59.com/qmEi5IYBdhLWcg3wwecN,我想知道如果attemptRotationToDeviceOrientation不能实现旋转,那么它有什么用处? 在iOS6之前,可以使用[UIDevice currentDevice] setOrientation来实现此操作。虽然以下代码是在iOS7中可行的,但它是一种方法并会产生编译警告,并且不会被App Store接受:objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait ); - John Stewart
1
我来这里说一下,自从XCode 8.3以来,有时模拟器上会出现调用失败的情况,但在设备上尝试时却可以正常工作。 - Juan Carlos Ospina Gonzalez
@bilobatum 你说的“所以我在短暂的动画期间关闭了界面旋转”是什么意思?你是如何做到的? - Borzh

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接