Подтвердить что ты не робот

IOS6: supportedInterfaceOrientations не работает (вызывается, но интерфейс по-прежнему вращается)

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

Следующий код работал, чтобы отключить ландшафтный режим на данном контроллере представления до iOS 6:

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

Поскольку shouldAutorotateToInterfaceOrientation устарел в iOS6, я заменил выше:

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMask.Portrait;
}

Этот метод корректно вызывается, когда появляется представление (я могу установить точку останова, чтобы это обеспечить), но интерфейс по-прежнему вращается в ландшафтном режиме, независимо от того, что я возвращаю маску только для портретных режимов. Что я делаю неправильно?

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

4b9b3361

Ответ 1

Если вы используете UINavigationController в качестве контроллера корневого окна, он будет его shouldAutorotate и supportedInterfaceOrientations, который будет вызываться.

То же, если вы используете UITabBarController и т.д.

Итак, нужно сделать так, чтобы подклассифицировать ваш контроллер навигации/вкладки и переопределить его методы shouldAutorotate и supportedInterfaceOrientations.

Ответ 3

В моем случае у меня есть UINavigationController и мой контроллер представления внутри. Мне пришлось подклассифицировать UINavigationController и, чтобы поддерживать только портрет, добавьте этот метод:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
}

Итак, в подклассе UINavigationController мне нужно проверить, какая ориентация поддерживается текущим topViewController.

- (NSUInteger)supportedInterfaceOrientations
{
    return [[self topViewController] supportedInterfaceOrientations];
}

Ответ 4

Одна вещь, которую я нашел, - это если у вас есть старое приложение, которое все еще делает

[window addSubView:viewcontroller.view];  //This is bad in so may ways but I see it all the time...

Вам нужно будет обновить его, чтобы:

[window setRootViewController:viewcontroller]; //since iOS 4

Как только вы сделаете это, ориентация начнет работать снова.

Ответ 5

Лучший способ для 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;
}

Ответ 6

Как указано другими, если вы используете UINavigationController и хотите настроить различные виды, вы захотите подклассифицировать UINavigationController и убедиться, что у вас есть эти два компонента:

@implementation CustomNavigationController

// -------------------------------------------------------------------------------
//  supportedInterfaceOrientations:
//  Overridden to return the supportedInterfaceOrientations of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  UIInterfaceOrientationMaskAllButUpsideDown when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (NSUInteger)supportedInterfaceOrientations
{
    return [self.topViewController supportedInterfaceOrientations]; 
}

// -------------------------------------------------------------------------------
//  shouldAutorotate
//  Overridden to return the shouldAutorotate value of the view controller
//  at the top of the navigation stack.
//  By default, UIViewController (and thus, UINavigationController) always returns
//  YES when the app is run on an iPhone.
// -------------------------------------------------------------------------------
- (BOOL)shouldAutorotate
{
    return [self.topViewController shouldAutorotate];
}

Тогда в любом представлении, которое является только портретом, вы должны включать:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

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

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAllButUpsideDown;
}

Ответ 7

В принципе, как указано выше, но более подробно:

  • Создайте новый файл, который является подклассом UINavigationController
  • Перейдите в свою раскадровку и затем нажмите на контроллер навигации, установите ее класс в тот, который вы только что создали.
  • В этом классе (.m файл) добавьте следующий код, чтобы он оставался в портретном режиме:

    (BOOL)shouldAutorotate
    {
      return NO;
    } 
    
    (NSUInteger)supportedInterfaceOrientations
    {
     return UIInterfaceOrientationMaskPortrait;
    }
    

Это сработало для меня

Ответ 8

Этот код работал у меня:

-(BOOL)shouldAutorotate {
     return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAll;
}

Ориентация iPhone/iPad App проверьте мой собственный ответ

Ответ 9

Лучший способ, я думаю, состоит в том, чтобы сделать категорию, а не подклассифицировать UINavigationController или UITabbarController

ваш UINavigationController + Rotation.h

#import <UIKit/UIKit.h>

@interface UINavigationController (Rotation)

@end

ваш UINavigationController + Rotation.m

#import "UINavigationController+Rotation.h"

@implementation UINavigationController (Rotation)

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

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

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


@end

Попробуйте, чтобы весь ваш контроллер импортировал эту категорию, и эта работа как шарм. Вы даже можете сделать контроллер не вращением и нажатием другого контроллера, который будет вращаться.

Ответ 10

Попробуйте добавить shouldAutorotate метод

Ответ 11

Во-первых, чтобы ваше приложение работало только в режиме, вы должны возвращать UIInterfaceOrientationMaskLandscape. Если вы хотите сохранить только портретный режим, вы делаете все правильно.

Просто добавьте ключ UISupportedInterfaceOrientations в Info.plist и назначьте значения ориентации интерфейса, которые ваше приложение намерено сохранить.

Кроме того, вы должны возвращать false из shouldAutoRotate, если вы хотите полностью избежать автоматического вращения. Но я предлагаю вам вернуться отсюда и указать правильные ориентации в методе supportedInterfaceOrientations.

Ответ 12

У меня такая же ситуация, как и вы. Я знаю, что вы уже приняли ответ, но я думал, что добавлю еще один. Так я понимаю, что новая версия системы ротации работает. Контроллер корневого представления является единственным контроллером вида, который когда-либо будет вызван. Я считаю, что аргументация заключается в том, что с контроллерами дочерних элементов часто не имеет смысла поворачивать свои представления, так как они все равно останутся в рамках контроллера корневого представления.

Итак, что происходит. Первый shouldAutorotate называется на контроллере корневого представления. Если NO возвращается, все останавливается. Если YES возвращается, то вызывается метод supportedInterfaceOrientations. Если ориентация интерфейса подтверждена в этом методе и глобально поддерживаемых ориентациях от Info.plist или делегата приложения, тогда представление будет вращаться. Перед вращением запрашивается метод shouldAutomaticallyForwardRotationMethods. Если YES (по умолчанию), то все дети получат методы will и didRotateTo..., а также родительский (и они, в свою очередь, отправят его своим детям).

Мое решение (пока есть более красноречивое) - запросить последний контроллер детского представления во время метода supportedInterfaceOrientations и вернуть его значение. Это позволяет мне вращать некоторые области, сохраняя при этом только портрет других. Я понимаю, что он хрупкий, но я не вижу другого способа, который не связан с усложнением событий вызовами, обратными вызовами и т.д.

Ответ 13

Если вы используете UINavigationController, вы должны реализовать shouldAutorotate и supportedInterfaceOrientations в подклассе UINavigationController.

Они могут управлять двумя шагами, если shouldAutorotate возвращает YES, тогда действует supportedInterfaceOrientations. Это очень приятная комбинация.

В этом примере мои главные представления - "Портрет", кроме CoverFlowView и PreviewView. Передача CoverFlowView в PreviewView, PreviewView хочет следовать за поворотом CoverFlowCView.

@implementation MyNavigationController

-(BOOL)shouldAutorotate
{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"PreviewView")])

return NO;

else

return YES;

}



-(NSUInteger)supportedInterfaceOrientations

{

if ([[self.viewControllers lastObject] isKindOfClass:NSClassFromString(@"CoverFlowView")])

return UIInterfaceOrientationMaskAllButUpsideDown;

else

return UIInterfaceOrientationMaskPortrait;

}

...

@end

Ответ 14

мое решение: subclassed UINavigationController и установите его как window.rootViewController

верхний диспетчер представления иерархии будет контролировать ориентацию, некоторые примеры кода: подклассы UINavigationController

Ответ 15

Ответы здесь указывали мне в правильном направлении, хотя я не мог заставить его работать, просто вырезая и вставляя, потому что я использую UINavigationControllers внутри UITabBarController. Поэтому моя версия в AppDelegate.m выглядит примерно так, что будет работать для UITabBarControllers, UINavigationControllers или UINavigationControllers в UITabBarController. Если вы используете другие пользовательские контроллеры сдерживания, вам нужно будет добавить их здесь (что является вроде обломка).

- (UIViewController*)terminalViewController:(UIViewController*)viewController
{
  if ([viewController isKindOfClass:[UITabBarController class]])
  {
    viewController = [(UITabBarController*)viewController selectedViewController];
    viewController = [self terminalViewController:viewController];
  }
  else if ([viewController isKindOfClass:[UINavigationController class]])
  {
    viewController = [[(UINavigationController*)viewController viewControllers] lastObject];
  }

  return viewController;
}

- (NSUInteger)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
  NSUInteger orientations = UIInterfaceOrientationMaskPortrait;
  UIViewController* viewController = [self terminalViewController:window.rootViewController];

  if (viewController)
    orientations = [viewController supportedInterfaceOrientations];

  return orientations;
}

Еще одна важная вещь: вы должны переопределить supportedInterfaceOrientations в подклассах UIViewController или по умолчанию будет указано то, что вы указали в своем Info.plist.