45

iOS 5中,我们可以像这样以编程方式更改设备方向:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

但是在iOS 6 setOrientation中已弃用,如何在iOS 6中以编程方式更改设备方向?

4

15 回答 15

49

这是我的“五分钱”,在 iOS7 上用 ARC 测试过

[[UIDevice currentDevice] setValue:
                      [NSNumber numberWithInteger: UIInterfaceOrientationPortrait]
                            forKey:@"orientation"];

这不会像 performSelector 那样生成“泄漏”警告。

UIAlertView - 使用此代码,当您在 view(will/Did) 出现期间打开 UIAlertView 时,您会注意到除此视图之外的所有视图都是纵向的(苹果,真的吗?)我无法强制视图重新定向但发现如果您在打开 UIAlertView 之前稍作延迟,然后视图有时间更改方向。

请注意,我将从 2014 年 9 月 12 日开始发布我的应用周,如果它通过或失败,我将更新帖子。

于 2014-06-17T08:57:54.300 回答
20

这不回答如何更改设备方向,而是提供可能对您有所帮助的附加信息。

iOS 6 UI 界面方向 - shouldAutorotateToInterfaceOrientation:不工作

方法shouldAutorotateToInterfaceOrientation : 在 iOS 6 中不受支持。它已弃用。以防万一如果你是一个新手,只是盯着可可工作,想知道为什么你的视图控制器在 iOS 6 中搞砸了,而在 iOS 5 中却完美无缺,只要知道shouldAutorotateToInterfaceOrientation : 不再受支持。即使它可能适用于 Xcode 4 到 4.3,但它不适用于 Xcode 4.5。

Apple 提供了一种新方法来完成这项工作,而且方式更加简洁。您改用supportedInterfaceOrientations。它返回视图控制器支持的所有界面方向,一个界面方向值的掩码。

UIInterfaceOrientationMask 枚举:

这些常量是用于指定视图控制器支持的界面方向的掩码位。

typedef enum {
    UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait),
    UIInterfaceOrientationMaskLandscapeLeft = (1 << UIInterfaceOrientationLandscapeLeft),
    UIInterfaceOrientationMaskLandscapeRight = (1 << UIInterfaceOrientationLandscapeRight),
    UIInterfaceOrientationMaskPortraitUpsideDown = (1 << UIInterfaceOrientationPortraitUpsideDown),
    UIInterfaceOrientationMaskLandscape =
        (UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight),
    UIInterfaceOrientationMaskAll =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortraitUpsideDown),
    UIInterfaceOrientationMaskAllButUpsideDown =
        (UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft |
    UIInterfaceOrientationMaskLandscapeRight),
} UIInterfaceOrientationMask;

使用 shouldAutorotateToInterfaceOrientation: 方法:

-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return UIInterfaceOrientationIsLandscapeRight(toInterfaceOrientation);
}

使用supportedInterfaceOrientations 方法:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

这些是在 iOS6 中向 UIViewController 添加的关于方向的方法

  1. UIViewController preferredInterfaceOrientationForPresentation

  2. UIViewController 应该自动旋转

  3. UIViewController 支持的接口方向

在 iOS6 中向 UIApplication 添加了有关方向的方法

  1. UIApplication supportedInterfaceOrientationsForWindow:

  2. UIInterfaceOrientationMask

于 2012-09-29T08:49:18.683 回答
20

我发现强制设备改变方向的最简单方法是呈现一个新的视图控制器(使用presentViewController:animated:completion:),其中新的视图控制器指定了一个特定的首选方向(通过实现方法-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation)。

当一个新的视图控制器出现时,正如预期的那样,方向将更改为新视图控制器首选的方向。因此,最简单的实现(最佳实践?)是将特定方向所需的所有功能嵌入到单独的视图控制器中,并根据需要呈现。系统会为您改变方向。

显然这可能不适合所有用例,但幸运的是,同样的技巧适用于强制设备改变现有视图控制器的方向。

诀窍是呈现一个具有您需要的特定首选方向的新视图控制器,然后立即隐藏它。当新的视图控制器出现时,这将导致方向临时改变。最好的部分是,当新的视图控制器被关闭时,原始(呈现)视图控制器 preferredInterfaceOrientationForPresentation会再次被查询,您可以在此处指定您想要的最终方向。

这里要注意的一件重要事情是在原始视图控制器中临时禁用自动旋转(当从新呈现的然后关闭的视图控制器返回时),这样当用户将手机旋转到新方向时,它不会触发了进一步的自动旋转。

以下代码应说明我的观点,我的示例强制旋转为纵向,如果您想要其他方向,只需相应更改即可。

假设您有一个名为 的原始视图控制器Original和一个名为 的临时视图控制器ForcePortrait

@interface Original : UIViewController
{
    BOOL orientationToPortrait; //should set to NO by default
}
@end

@implementation Original
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation
{
    if(orientationToPortrait)
    {
        //when we manually changed, show in Portrait
        return UIInterfaceOrientationPortrait;
    }
    else
    {
        //before manual orientation change, we allow any orientation
        return self.interfaceOrientation;
    }
}

-(BOOL) shouldAutorotate
{
    //we should 'lock' the rotation once we manually change it
    return !orientationToPortrait;
}

-(void) changeOrientationToPortrait
{
    //Sample method to change the orientation
    //when called, will show (and hide) the temporary view
    //Original.preferredInterfaceOrientationForPresentation will be called again after this method

    //flag this to ensure that we tell system we prefer Portrait, whenever it asked again
    orientationToPortrait = YES;

    //presenting the following VC will cause the orientation to temporary change
    //when the new VC is dismissed, system will ask what is our (Original) orientation preference again
    ForcePortrait* forcePortrait = [[ForcePortrait alloc] init];
    [self presentViewController:forcePortrait animated:NO completion:^{
        [forcePortrait dismissViewControllerAnimated:NO completion:nil];
    }];
}


@end

@interface ForcePortrait : UIViewController
@end

@implementation ForcePortrait
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationPortrait;
}
@end
于 2013-01-03T11:01:05.803 回答
10

尝试这个:

#import <objc/message.h>

if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
        }
    }
于 2012-10-09T13:59:33.610 回答
5

您应该放置
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
在您的 AppDelegatedidFinishLaunchingWithOptions方法中。

然后,在您的应用程序中的任何位置,您都可以通过以下方式获取当前方向:

UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

并通过以下方式测试方向:

UIInterfaceOrientationIsPortrait(orientation) 
UIInterfaceOrientationIsLandscape(orientation)

作为,像

if (UIDeviceOrientationIsLandscape([UIDevice currentDevice].orientation))
{
    // code for landscape orientation
     // OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];
     //  OR
    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeLeft];

}
else if (UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation))
{
    // code for Portrait orientation
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortraitUpsideDown];
    //  OR
   [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait];
}
于 2012-09-29T07:11:12.767 回答
4

此代码适用于 iOS 8 或更高版本

NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
于 2015-10-24T03:11:44.157 回答
2

如果您想避免使用运行时库,请对 Bissy 的答案稍作修改:

if (UIDeviceOrientationIsLandscape([[UIDevice currentDevice] orientation]))
{
    if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
    {
        int orientationPortrait = UIInterfaceOrientationPortrait;
        NSMethodSignature *sig = [[UIDevice currentDevice] methodSignatureForSelector:@selector(setOrientation:)];
        NSInvocation* invo = [NSInvocation invocationWithMethodSignature:sig];
        [invo setTarget:[UIDevice currentDevice]];
        [invo setSelector:@selector(setOrientation:)];
        [invo setArgument:&orientationPortrait atIndex:2];
        [invo invoke];
    }
}
于 2013-11-19T23:36:46.673 回答
2

@implementation UINavigationController(自动旋转)

 -(NSUInteger)supportedInterfaceOrientations
 {
   //make the check for iphone/ipad here

    if(IPHONE)
    {
      return UIInterfaceOrientationMaskPortrait;
    } 
    else
    {
      return UIInterfaceOrientationMaskLandscape;
    }
 }

 - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
 {
    return UIInterfaceOrientationPortrait;
 }

 - (BOOL)shouldAutorotate
 {
    return NO;
 }
于 2013-11-04T06:44:33.863 回答
2

Apple 在中以编程方式更改设备方向非常困难(请注意)。

据我所知,完成您所要求的唯一方法是模拟设备方向的变化。

使用setTransform旋转UIView并重新应用其自己的框架会产生所需的结果。

[YourView setTransform:CGAffineTransformMakeRotation(1.57)];
[YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];

当设备物理方向发生变化时,我们可以撤消转换。

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    [YourView setTransform:CGAffineTransformMakeRotation(0)];
    [YourView setFrame:CGRectMake(0, 0, YourView.frame.size.width, YourView.frame.size.height)];
}
于 2012-10-05T12:16:13.870 回答
2

试试这个……对我有用……

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview]; [window addSubview:view];
于 2012-10-22T11:14:30.263 回答
2

这适用于 iOS7,强制自动旋转为纵向。

//In your viewController.m
#import <objc/message.h>

// for autorotate viewController to portraid
- (void)viewWillAppear:(BOOL)animated {
    UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
    switch (orientationStatusBar) {
        case UIInterfaceOrientationPortrait:break;
        case UIInterfaceOrientationLandscapeLeft:
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
            break;
        case UIInterfaceOrientationLandscapeRight:
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait);
            break;
        default:
            break;
    }
}

// this permit autorotate
- (BOOL) shouldAutorotate
{
   // this lines permit rotate if viewController is not portrait
    UIInterfaceOrientation orientationStatusBar =[[UIApplication sharedApplication] statusBarOrientation];
    if (orientationStatusBar != UIInterfaceOrientationPortrait) {
        return YES;
    }
    //this line not permit rotate is the viewController is portrait
    return NO;
}

注意:我在我的应用程序中实现了这个选项,但可能会被 Apple 拒绝(2012 年 10 月对 Austin 的 Sergey K. 编辑 6 的评论)。

于 2014-01-15T16:31:06.117 回答
1
if (self.interfaceOrientation != UIInterfaceOrientationLandscapeRight) {
// http://stackoverflow.com/questions/181780/is-there-a-documented-way-to-set-the-iphone-orientation
// http://openradar.appspot.com/radar?id=697
// [[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]; // Using the following code to get around apple's static analysis...
[[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight];
}
于 2013-08-30T08:41:26.690 回答
0
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
    // Return YES for supported orientations
   return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
   return  interfaceOrientation == UIInterfaceOrientationPortrait
           || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ;
}
于 2013-02-22T10:20:55.017 回答
0

这适用于 Xcode 6 和 5。

- (BOOL)shouldAutorotate {return YES;}
- (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}
于 2014-10-12T13:47:53.747 回答
0

有趣的是,其他人在没有这样设置后没有遇到问题:

+ (void)setOrientation:(UIDeviceOrientation)orientation {
    [UIDevice.currentDevice setValue:@(orientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
    [UIDevice.currentDevice setValue:@(UIDeviceOrientationUnknown) forKey:@"orientation"];
}

我的要求是能够强制方向,然后再次旋转到设备自然方向......有 UIDeviceOrientationDidChangeNotification 可以让你获得信息以女巫方向旋转设备但实际上如果你不设置它将部分不起作用在 UIDevice 中更改方向后立即未知,还有更多细节可以让它变得酷但会离开它,因为它超出了这个简单问题的上下文。

于 2019-09-24T06:08:44.440 回答