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 для портрета, но оставить все варианты для других контроллеров представления?

5 ответов


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

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

  1. создайте пользовательский контроллер навигации, который является подклассом UINavigationController, в Вашему .файл м:

     - (BOOL)shouldAutorotate
     {
          return self.topViewController.shouldAutorotate;
     }
     - (NSUInteger)supportedInterfaceOrientations
     {
          return self.topViewController.supportedInterfaceOrientations;
     }
    
  2. в своем 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;
    
      }
    
  3. в вашем rootViewController, для любого события нажмите второй контроллер представления, сделайте следующее:

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

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

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

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

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

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

надеюсь, что это помогает.


в 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

для viewcontroller вы хотите ориентацию поддержки

[singleton setOrientationSupport:YES];

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

[singleton setOrientationSupport:NO];

поместите это в свой навигационный контроллер:

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

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskAll;
}

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

- (BOOL)shouldAutorotate
{
    return NO;
}

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


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

  1. суб-класс навигационного контроллера:

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    
        if let visibleView = self.visibleViewController {
            return visibleView.supportedInterfaceOrientations()
        } else {
            return UIInterfaceOrientationMask.All
        }
    }
    
  2. под-вид (корневой вид) nav контроллер:

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

Я искал решение в течение нескольких часов!

Итак, после реализации необходимых методов везде. 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 я связал представления с этим сегментом (показывает):

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"];

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