Как программно изменить ориентацию устройства в iOS 6

В iOS 5 мы могли программно изменить ориентацию устройства следующим образом:

[[UIDevice currentDevice] setOrientation:UIInterfaceOrientationLandscapeRight];

Но в iOS 6 setOrientation устарела, как я могу программно изменить ориентацию устройства в iOS 6?

Ответ 1

Вот мои "пять центов", протестированные на iOS7 с ARC

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

Это не генерирует предупреждение об утечке, поскольку выполняет функцию Selecter.

UIAlertView - с этим кодом, когда вы откроете UIAlertView во время просмотра (будет/Did), вы заметите, что все, кроме этого вида, находятся в портрете (яблоко, правда?) Я не смог чтобы заставить представление переориентироваться, но обнаружил, что если вы положите небольшую задержку перед открытием UIAlertView, тогда у представления есть время, чтобы изменить ориентацию.

Примечание Я освобождаю свою неделю приложения начиная с 12/09/2014, и я обновляю сообщение, если он пройдет или завершится с ошибкой.

Ответ 2

Это не отвечает, как изменить ориентацию устройства, но дополнительную информацию, которая может вам помочь.

Ориентация интерфейса iOS 6 UI - должно быть активировано для интерфейса: не работает

Метод shouldAutorotateToInterfaceOrientation: НЕ поддерживается в iOS 6. Его устарело. На всякий случай, если вы новичок, который просто смотрел на работу в cocoa и задавался вопросом, почему ваш контроллер представления данных испорчен в iOS 6 и отлично подходит для iOS 5, просто знайте, что shouldAutorotateToInterfaceOrientation: больше не поддерживается. Несмотря на то, что он может хорошо работать с Xcode 4 до 4.3, он не будет работать с Xcode 4.5.

Apple предлагает новый метод, чтобы сделать эту вещь более чистым способом. Вместо этого вы используете supportedInterfaceOrientations. Он возвращает все ориентации интерфейса, поддерживаемые контроллером представления, маску значений ориентации интерфейса.

UIInterfaceOrientationMask Enum:

Эти константы являются битами маски для указания поддерживаемых ориентаций интерфейса контроллера.

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

Это дополнительные методы для UIViewController относительно ориентации в iOS6

Добавлены методы для UIApplication относительно ориентации в iOS6

Ответ 3

Я выяснил, что самый простой способ заставить устройство изменить ориентацию - представить новый контроллер представления (используя 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

Ответ 4

Попробуйте следующее:

#import <objc/message.h>

if(UIDeviceOrientationIsLandscape(self.interfaceOrientation)){
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)])
        {
            objc_msgSend([UIDevice currentDevice], @selector(setOrientation:), UIInterfaceOrientationPortrait );
        }
    }

Ответ 5

Вы должны разместить [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
в вашем методе AppDelegate didFinishLaunchingWithOptions.

Затем в любом месте приложения вы можете получить текущую ориентацию с помощью:

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

Ответ 6

Этот код предназначен для iOS 8 или более поздней версии

NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];

Ответ 7

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

Ответ 8

Попробуй это... Это сработало для меня...

UIWindow *window = [[UIApplication sharedApplication] keyWindow];
UIView *view = [window.subviews objectAtIndex:0];
[view removeFromSuperview]; [window addSubview:view];

Ответ 9

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

Ответ 10

Небольшая модификация ответа Bissy, если вы хотите избежать использования Runtime Library:

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

Ответ 11

Это работает для 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 (комментарий для Austin для отредактированного 6 Сергея К. в октябрь 2012 года).

Ответ 12

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 static analysis...
[[UIDevice currentDevice] performSelector:NSSelectorFromString(@"setOrientation:") withObject:(id)UIInterfaceOrientationLandscapeRight];
}

Ответ 13

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{
    // Return YES for supported orientations
   return NO;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
   return  interfaceOrientation == UIInterfaceOrientationPortrait
           || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown ;
}

Ответ 14

Это работает для меня на Xcode 6 и 5.

- (BOOL)shouldAutorotate {return YES;}
- (NSUInteger)supportedInterfaceOrientations {return (UIInterfaceOrientationMaskPortrait);}

Ответ 15

Интересно, что другие не столкнулись с проблемами после того, как не настроили это так:

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

Мое требование состояло в том, чтобы иметь возможность принудительно установить ориентацию и затем снова повернуть ее в естественную ориентацию устройства... есть UIDeviceOrientationDidChangeNotification, которая может получить информацию о ориентации устройства, чтобы повернуть устройство назад, но на самом деле это отчасти не будет работать, если вы не Установите значение неизвестно сразу после того, как вы изменили ориентацию в UIDevice, также есть дополнительные подробности, которые сделают его крутым, но оставим его, поскольку это выходит за рамки этого простого вопроса.