IOS6: supportedInterfaceOrientations не работает (вызывается, но интерфейс по-прежнему вращается)
В моем приложении у меня несколько просмотров, некоторые представления должны поддерживать как портрет, так и пейзаж, в то время как другие виды должны поддерживать только портрет. Таким образом, в резюме проекта я выбрал все ориентации.
Следующий код работал, чтобы отключить ландшафтный режим на данном контроллере представления до iOS 6:
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
Поскольку shouldAutorotateToInterfaceOrientation устарел в iOS6, я заменил выше:
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMask.Portrait;
}
Этот метод корректно вызывается, когда появляется представление (я могу установить точку останова, чтобы это обеспечить), но интерфейс по-прежнему вращается в ландшафтном режиме, независимо от того, что я возвращаю маску только для портретных режимов. Что я делаю неправильно?
Кажется, что в настоящее время невозможно создать приложение, которое имеет разные требования к ориентации для каждого представления. Похоже, что они придерживаются только ориентации, указанной в резюме проекта.
Ответы
Ответ 1
Если вы используете UINavigationController в качестве контроллера корневого окна, он будет его shouldAutorotate
и supportedInterfaceOrientations
, который будет вызываться.
То же, если вы используете UITabBarController и т.д.
Итак, нужно сделать так, чтобы подклассифицировать ваш контроллер навигации/вкладки и переопределить его методы shouldAutorotate
и supportedInterfaceOrientations
.
Ответ 2
попробуйте изменить этот код в AppDelegate.m
// self.window.rootViewController = self.navigationController;
[window setRootViewController:navigationController];
это полный ответ
shouldAutorotateToInterfaceOrientation не вызывается в iOS 6
XD
Ответ 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.