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

Поскольку ShouldAutorotateToInterfaceOrientation устарел в iOS 6, и я использовал это для принудительного отображения определенного вида только для портрета, каков правильный способ сделать это в iOS 6? Это только для одной области моего приложения, все другие виды могут вращаться.

Ответ 1

Если вы хотите, чтобы все наши навигационные контроллеры соблюдали контроллер верхнего уровня, вы можете использовать категорию, чтобы вам не пришлось проходить и менять кучу имен классов.

@implementation UINavigationController (Rotation_IOS6)

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

@end

Как следует из нескольких замечаний, это быстрое решение проблемы. Лучшим решением является подкласс UINavigationController и поместите туда эти методы. Подкласс также помогает поддерживать 6 и 7.

Ответ 2

Лучший способ для iOS6 определен в "iOS6 By Tutorials" командой Ray Wenderlich - http://www.raywenderlich.com/ и лучше, чем подклассы UINavigationController для большинства случаев.

Я использую iOS6 с раскадрой, которая включает в себя UINavigationController в качестве начального контроллера представления.

//AppDelegate.m - этот метод недоступен до iOS6, к сожалению

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;

if(self.window.rootViewController){
    UIViewController *presentedViewController = [[(UINavigationController *)self.window.rootViewController viewControllers] lastObject];
    orientations = [presentedViewController supportedInterfaceOrientations];
}

return orientations;
}

//MyViewController.m - вернуть любые ориентации, которые вы хотите поддерживать для каждого UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

Ответ 3

Этот ответ касается вопросов, заданных в комментариях к сообщению OP:

Чтобы заставить представление появиться в заданной ориентации, сделайте следующее в viewWillAppear:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
    UIViewController *c = [[UIViewController alloc]init];
    [self presentModalViewController:c animated:NO];
    [self dismissModalViewControllerAnimated:NO];
}

Это немного взломать, но это вынуждает UIViewController быть представленным на портрете, даже если предыдущий контроллер был ландшафтным.

ОБНОВЛЕНИЕ для iOS7

Приведенные выше методы теперь устарели, поэтому для iOS 7 используйте следующее:

UIApplication* application = [UIApplication sharedApplication];
if (application.statusBarOrientation != UIInterfaceOrientationPortrait)
{
     UIViewController *c = [[UIViewController alloc]init];
     [c.view setBackgroundColor:[UIColor redColor]];
     [self.navigationController presentViewController:c animated:NO completion:^{
            [self.navigationController dismissViewControllerAnimated:YES completion:^{
            }];
     }];
}

Интересно, что на момент написания настоящего документа необходимо либо афишировать настоящее, либо увольнять. Если нет, тогда вы получите белый экран. Не знаю, почему это заставляет работать, но это так! Визуальный эффект отличается в зависимости от анимации.

Ответ 4

Таким образом, я столкнулся с той же проблемой при отображении только модальных просмотров. Обычно я создавал UINavigationController, устанавливал viewController как rootViewController, а затем отображал UINavigationController как модальное представление. Но с iOS 6, viewController теперь попросит навигационный контроллер для поддерживаемых ориентаций интерфейса (который по умолчанию теперь для iPad и всего, но перевернутый для iPhone).

Решение: мне пришлось подклассифицировать UINavigationController и переопределить методы авторотации. Вид хромой.

- (BOOL)shouldAutorotate {
    return NO;
}

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}
// pre-iOS 6 support 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return (toInterfaceOrientation == UIInterfaceOrientationPortrait);
}

Ответ 5

IOS 5

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{

    return (interfaceOrientation == UIInterfaceOrientationPortrait);

}

IOS 6

-(BOOL)shouldAutorotate{
    return YES;
}

-(NSInteger)supportedInterfaceOrientations{

    //    UIInterfaceOrientationMaskLandscape;
    //    24
    //
    //    UIInterfaceOrientationMaskLandscapeLeft;
    //    16
    //
    //    UIInterfaceOrientationMaskLandscapeRight;
    //    8
    //
    //    UIInterfaceOrientationMaskPortrait;
    //    2

    //    return UIInterfaceOrientationMaskPortrait; 
    //    or
          return 2;
}

Ответ 6

Я не согласен с ответом @aprato, потому что методы вращения UIViewController объявлены самими категориями, что приводит к поведению undefined, если вы переопределите его в другой категории. Его безопаснее переопределять в подклассе UINavigationController (или UITabBarController)

Кроме того, это не распространяется на сценарий, в котором вы нажимаете/представляете/выпадаете из пейзажного вида только на портретный только VC или наоборот. Чтобы решить эту сложную проблему (никогда не рассматриваемую Apple), вы должны:

В iOS <= 4 и iOS >= 6:

UIViewController *vc = [[UIViewController alloc]init];
[self presentModalViewController:vc animated:NO];
[self dismissModalViewControllerAnimated:NO];
[vc release];

В iOS 5:

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

Они будут ДЕЙСТВИТЕЛЬНО заставить UIKit переоценить все ваши shouldAutorotate, supportedInterfaceOrientations и т.д.

Ответ 7

У меня очень хороший подход к смешиванию fooobar.com/questions/67650/... и fooobar.com/questions/31628/...

-(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window{
    NSUInteger orientations = UIInterfaceOrientationMaskAllButUpsideDown;


    if(self.window.rootViewController){
        UIViewController *presentedViewController = [self topViewControllerWithRootViewController:self.window.rootViewController];
        orientations = [presentedViewController supportedInterfaceOrientations];
    }

    return orientations;
}

- (UIViewController*)topViewControllerWithRootViewController:(UIViewController*)rootViewController {
    if ([rootViewController isKindOfClass:[UITabBarController class]]) {
        UITabBarController* tabBarController = (UITabBarController*)rootViewController;
        return [self topViewControllerWithRootViewController:tabBarController.selectedViewController];
    } else if ([rootViewController isKindOfClass:[UINavigationController class]]) {
        UINavigationController* navigationController = (UINavigationController*)rootViewController;
        return [self topViewControllerWithRootViewController:navigationController.visibleViewController];
    } else if (rootViewController.presentedViewController) {
        UIViewController* presentedViewController = rootViewController.presentedViewController;
        return [self topViewControllerWithRootViewController:presentedViewController];
    } else {
        return rootViewController;
    }
}

и вернуть любые ориентации, которые вы хотите поддерживать для каждого UIViewController

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

Ответ 8

Не скучно здесь, но не могли бы вы поделиться своим подклассом? Спасибо.

edit: ну, я, наконец, сделал это, подкласс был мертв, просто сделать. Мне просто нужно было объявить navigationController в AppDelegate как UINavigationControllerSubclass вместо стандартного UINavigationController, а затем изменить ваш подкласс следующим образом:

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

поэтому я могу установить любое представление, которое я хочу повернуть или нет, вызывая в viewDidLoad

_navController = (UINavigationController *)self.navigationController;
[_navController setShouldRotate : YES / NO]

Надеюсь, что эта настройка поможет другим, спасибо за ваш совет!

Совет. Используйте

- (NSUInteger)supportedInterfaceOrientations

в ваших диспетчерах просмотра, поэтому вы не получите портретный вид в альбомной ориентации или наоборот.

Ответ 9

У меня есть относительно сложное универсальное приложение, использующее UISplitViewController и UISegmentedController, и у вас есть несколько представлений, которые должны быть представлены в Landscape, используя presentViewController. Используя предложенные выше методы, я смог заставить iPhone ios 5 и 6 работать приемлемо, но по какой-то причине iPad просто отказался представить как Пейзаж. Наконец, я нашел простое решение (реализованное после часов чтения, проб и ошибок), которое работает как для устройств, так и для ios 5 и 6.

Шаг 1) На контроллере укажите требуемую ориентацию (более или менее, как указано выше)

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    NSInteger mask = UIInterfaceOrientationMaskLandscape;
    return mask;

}

Шаг 2) Создайте простой подкласс UINavigationController и реализуйте следующие методы.

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

Шаг 3) Представьте свой viewController

vc = [[MyViewController alloc]init];
MyLandscapeNavigationController *myNavigationController = [[MyLandscapeNavigationController alloc] initWithRootViewController:vc];
[self myNavigationController animated:YES completion:nil];

Надеюсь, это кому-то поможет.

Ответ 10

Я сам не тестировал его, но в документации указано, что теперь вы можете переопределить эти методы: supportedInterfaceOrientations и preferredInterfaceOrientationForPresentation.

Возможно, вы достигнете того, чего хотите, и установите только ту ориентацию, которая вам нужна в этих методах.

Ответ 11

Ответы с использованием подклассов или категорий, чтобы позволить VC в классах UINavigationController и UITabBarController работать хорошо. Запуск режима портретирования только с контроллера панели ландшафта не удался. Если вам нужно это сделать, используйте трюк отображения и скрытия неанимированного модального представления, но сделайте это в методе viewDidAppear. Это не сработало для меня в viewDidLoad или viewWillAppear.

Кроме того, решения выше работают нормально.

Ответ 12

Для Monotouch вы можете сделать это следующим образом:

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
    {
    return UIInterfaceOrientationMask.LandscapeRight;
}

public override UIInterfaceOrientation PreferredInterfaceOrientationForPresentation()
    {
    return UIInterfaceOrientation.LandscapeRight;
}

Ответ 13

Я вижу много ответов, но не получаю особую идею и не отвечаю за ориентацию, но вижу, что ссылка хорошо понимает ориентацию и удаляет сильное вращение для ios6.

http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

Я думаю, что это полная помощь.

Ответ 14

Просто перейдите в project.plist, затем добавьте Поддерживаемую ориентацию интерфейса, а затем добавьте только портрет (нижняя кнопка дома) и портрет (кнопка верхнего дома).

Вы можете добавить или удалить ориентацию в соответствии с требованиями вашего проекта.

Спасибо

Ответ 15

1) Проверьте настройки проекта и info.plist и убедитесь, что выбраны только те ориентации, которые вы хотите.

2) добавьте следующие методы в ваш самый верхний контроллер (контроллер навигационной панели/контроллера таблеток)

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

3) добавьте следующие методы в делегат вашего приложения

- (NSUInteger) supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;

}

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait;

}

Ответ 16

Поместите это в .m файл каждого ViewController, который вы не хотите вращать:

- (NSUInteger)supportedInterfaceOrientations
{
    //return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
    return UIInterfaceOrientationMaskPortrait;
}

Подробнее см. здесь.