it-swarm.com.ru

Как заставить UIViewController для книжной ориентации в iOS 6

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

85
Neal

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

@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.

117
Anthony

Лучший способ для iOS6, в частности, отмечен в "Руководствах по iOS6" командой 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;
}
63
Phil

Этот ответ относится к вопросам, заданным в комментариях к посту ОП:

Чтобы заставить вид отображаться в заданной ориентации, поместите в 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:^{
            }];
     }];
}

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

39
Craig Watkinson

Поэтому я столкнулся с той же проблемой при отображении только портретных модальных видов. Обычно я создаю 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);
}
36
rocky

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;
}
15
Roshan Jalgaonkar

Я не согласен с ответом @aprato, потому что методы ротации UIViewController объявляются в самих категориях, что приводит к неопределенному поведению, если вы переопределяете его в другой категории. Безопаснее переопределить их в подклассе 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 переоценить все ваши mustAutorotate, supportInterfaceOrientations и т.д.

10
Rafael Nobre

У меня очень хороший подход к смешиванию https://stackoverflow.com/a/13982508/2516436 и https://stackoverflow.com/a/17578272/2516436

-(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;
}
3
Alex Guerra

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

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

- (BOOL)shouldAutorotate {
    return _shouldRotate;
}

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

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

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

Совет: используйте

- (NSUInteger)supportedInterfaceOrientations

в контроллерах вида, так что вы не получите желаемый портрет в горизонтальной или наоборот.

1
Roland

У меня есть относительно сложное универсальное приложение, использующее UISplitViewController и UISegmentedController, и у меня есть несколько представлений, которые должны быть представлены в альбомной ориентации с использованием presentViewController. Используя методы, предложенные выше, я смог заставить iPhone ios 5 & 6 работать приемлемо, но по какой-то причине iPad просто отказался представить его как Landscape. Наконец, я нашел простое решение (реализованное после часов чтения, проб и ошибок), которое работает как на устройствах, так и на 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];

Надеюсь, это кому-нибудь пригодится.

1
user216661

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

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

0
Peter

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

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

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

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

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

0
J_D

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

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

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

0
PeterParker