ViewController в изменении ориентации UINavigationController

Итак, у меня есть следующая иерархия:

UINavigationController → RootViewController (UIViewController) → UITableViewController → DetailViewController (UIViewController)

Я хочу заблокировать ориентацию на RootViewController только для портрета, но оставить все ориентации для остальных контроллеров представления.

Если я поместил это подклассом UINavigationController:

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

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

Все контроллеры просмотра затем заблокированы для портрета.

Мой вопрос в том, есть ли способ заблокировать только RootViewController для Portrait, но оставить все опции для других контроллеров представлений?

Ответ 1

проверьте ссылку здесь для исправления авторотации в iOS 6 и установите ориентацию поддержки для каждого представления: http://www.disalvotech.com/blog/app-development/iphone/ios-6-rotation-solution/

Вот что вы могли бы сделать:

  • Создайте настраиваемый контроллер навигации, который является подклассом UINavigationController, в вашем файле .m:

     - (BOOL)shouldAutorotate
     {
          return self.topViewController.shouldAutorotate;
     }
     - (NSUInteger)supportedInterfaceOrientations
     {
          return self.topViewController.supportedInterfaceOrientations;
     }
    
  • В AppDelegate.h,

      @interface AppDelegate : UIResponder <UIApplicationDelegate> {
    
          UINavigationController *navigationController;
          ViewController *viewController;
      }
    
      @property (strong, nonatomic) UIWindow *window;
      @property (strong, nonatomic) ViewController *viewController;
    

    и в AppDelegate.m,

      - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
      {
            // set initial view
           self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    
           viewController = [[ViewController alloc] initWithNibName:@"RootViewController" bundle:nil];
    
           navigationController = [[CustomNavigationController alloc]
                        initWithRootViewController:viewController]; // iOS 6 autorotation fix
           [navigationController setNavigationBarHidden:YES animated:NO];
    
            self.window = [[UIWindow alloc]
               initWithFrame:[[UIScreen mainScreen] bounds]];
    
            [self.window setRootViewController:navigationController]; // iOS 6 autorotation fix
            //[self.window addSubview:navigationController.view];
    
            [self.window makeKeyAndVisible];
    
    
             return YES;
      }
    
    
      - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  // iOS 6 autorotation fix
      {
              return UIInterfaceOrientationMaskAll;
    
      }
    
  • в вашем rootViewController, для чего бы то ни было событие, нажмите второй контроллер просмотра, сделайте следующее:

      - (IBAction)pushSecondViewController:(id)sender {
    
        // push second view controller
        SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondViewController" bundle:nil];
        [self.navigationController pushViewController:secondViewController animated:YES];
       }
    
  • в каждом контроллере представления добавьте

       - (BOOL)shouldAutorotate{}
       - (NSUInteger)supportedInterfaceOrientations{}
    

    для iOS 6, вы можете установить каждый контроллер вида независимо от ориентации, которую вы хотите по отдельности.

    для iOS 5 и ниже вы можете установить

       - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation{}
    

Все кредиты принадлежат Джону ДиСалво, который написал пример приложения в ссылке.

Надеюсь, что это поможет.

Ответ 2

в singleton

-(void)setOrientationSupport:(BOOL)flag{

    flag_orientationSupport_ = flag;
}

-(BOOL)getOrientationSupport{

    return flag_orientationSupport_;
}

в appdelegate

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

    if ([singleton getOrientationSupport])
        return UIInterfaceOrientationMaskAll;
    else
        return UIInterfaceOrientationMaskPortrait;
}

добавить следующий код в viewwillappear

для диспетчера представлений, для которого вы хотите поддерживать ориентацию

[singleton setOrientationSupport:YES];

для тех контроллеров, которым вы хотите отключить ориентацию

[singleton setOrientationSupport:NO];

Ответ 3

Поместите это в свой контроллер Nav:

- (BOOL)shouldAutorotate
{
    return self.topViewController.shouldAutorotate;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

Теперь добавьте это в свой корневой контроллер:

- (BOOL)shouldAutorotate
{
    return NO;
}

Это должно сделать это!

Ответ 4

Чтобы делегировать ответственность за определение разрешенных ориентаций подзонам UINavigationController, можно использовать свойство visibleViewController навигационного контроллера, чтобы заставить контроллер навигации "спросить" его дочерние представления для их поддерживаемых ориентаций. Следующий код должен работать (Swift):

  • Подклассифицированный контроллер навигации:

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    
        if let visibleView = self.visibleViewController {
            return visibleView.supportedInterfaceOrientations()
        } else {
            return UIInterfaceOrientationMask.All
        }
    }
    
  • Под-просмотр (корневой режим) навигационного контроллера:

    // Restrict to portrait
    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
    

Ответ 5

Я искал решение часами!

Итак, после внедрения необходимых методов повсюду. shouldAutorotate не нужно устанавливать в YES, потому что он уже установлен по умолчанию:

- (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskPortrait;
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{
     return UIInterfaceOrientationPortrait;
}

Когда пришло время показать UIViewController, для которого требуется ориентация, отличная от других представлений, я создал UIStoryboardSegue с этой реализацией внутри:

#import "Showing.h"

@implementation Showing

- (void)perform{
    NSLog(@"Showing");
    UIViewController *sourceVC = self.sourceViewController;
    UIViewController *presentingVC = self.destinationViewController;

    [sourceVC.navigationController presentViewController:presentingVC 
                                                animated:YES 
                                              completion:nil];
}

@end

Внутри UIStoryboard я связал просмотры с этим segue (, показывая):

enter image description here

Это просто важно, вы используете

presentViewController:animated:completion:

И НЕ

pushViewController:animated:

в противном случае ориентация не будет определена снова.


Я пробовал такие вещи, как
[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait];

ИЛИ этот внутри UIViewController, где ориентация должна измениться, и я также попытался вызвать его внутри моего пользовательского UIStoryboardSegues до presentingViewController и dismissViewController:

[UIViewController attemptRotationToDeviceOrientation];

ИЛИ

NSNumber *numPortrait = [NSNumber numberWithInt:UIInterfaceOrientationPortrait];
[[UIDevice currentDevice] setValue:numPortrait forKey:@"orientation"];

Но никто из них не работал. Конечно, последний пример не должен быть вариантом, потому что если яблоко изменит что-либо из их api, это может вызвать проблемы внутри вашего приложения.

Я также попытался использовать метод AppDelegate и всегда определял ориентацию внутри этого метода после поиска правильного UIInterfaceOrientation фактического visibleViewController, но иногда это случалось при сбое при переключении с одной на другую. Поэтому я все еще удивляюсь, почему это стало настолько сложным, и, похоже, также нет никакой документации, где это объясняется правильно. Даже после эта часть не помогла мне.