iPhone: только в альбомной ориентации после первого добавления addSubview UITableViewController не вращается должным образом

StackOverflow https://stackoverflow.com/questions/1632117

  •  06-07-2019
  •  | 
  •  

Вопрос

Минимальный иллюстративный проект XCode для этого доступен на github .

В моем UIWindow, когда я добавляю второй (и последующий) UITableView как подпредставления, они не вращаются должным образом и, таким образом, появляются вбок. Это проверено только в симуляторе. Вот небольшой код для вас:

- (void)applicationDidFinishLaunching:(UIApplication *)application {
    ShellTVC* viewA = [[ShellTVC alloc] initWithTitle:@"View A"];
    ShellTVC* viewB = [[ShellTVC alloc] initWithTitle:@"View B"];

    // The first subview added will rotate to landscape correctly. 
    // Any subsequent subview added will not.

    // You may try this by various commentings and rearranging of these two statements.

    [window addSubview:[viewA tableView]];
    [window addSubview:[viewB tableView]];

    [window makeKeyAndVisible];
}

viewB появляется сбоку. Закомментируйте addSubview для viewB, и viewA появится правильно. Сделайте это только для viewA, и viewB появится правильно.

Я не создаю эти UITableViewControllers через NIB, хотя UIWindow есть.

Если вам интересно, ShellTVC является UITableViewController и реализует этот метод:

- (BOOL) shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
 return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}

Кроме того, я установил для UIInterfaceOrientation в файле plist значение UIInterfaceOrientationLandscapeLeft.

Вероятно, связанные - и без ответа - ТАКИЕ вопросы здесь и здесь .

Это было полезно?

Решение

Я думаю, что нашел способ - возможно, правильный - сделать это. <Ол>

  • Создайте " мастер " Подкласс UIViewController, который реализует shouldAutorotate ... и добавляет это как единственный вид в вашем окне.
  • Чтобы переключаться между viewA или viewB, используйте комбинацию dismissModalViewControllerAnimated: & amp; presentModalViewController: animated: на этом главном контроллере представления.
  • Вот некоторый код:

    // this doesn't really do much but implement shouldAutorotate...
    @interface MasterViewController : UIViewController
    @end
    
    @implementation MasterViewController
    - (BOOL) shouldAutorotateToInterfaceOrientation(UIInterfaceOrientation)interfaceOrientation {
         return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft);
    }
    @end
    
    @interface MyAppDelegate : NSObject <UIApplicationDelegate> {
        MasterViewController* masterVC;
        UIViewController* activeTVC;
        UIViewController* onDeckTVC;
    }
    @end
    
    - (void)applicationDidFinishLaunching:(UIApplication *)application {
        UIViewController* masterVC = [[MasterViewController alloc] init];        
        activeTVC = [[ShellTVC alloc] initWithTitle:@"View A"];
        onDeckTVC = [[ShellTVC alloc] initWithTitle:@"View B"];
        [window addSubview:masterView.view];
        [window makeKeyAndVisible];
        [masterVC presentModalViewController:activeTVC animated:NO];
    }
    
    // you would call this to toggle between "View A" and "View B"
    - (void)toggleTVC {
        UITableViewController *hold = activeTVC;
        activeTVC = onDeckTVC;
        onDeckTVC = hold;
        [masterVC dismissModalViewControllerAnimated:NO];   
        [masterVC presentModalViewController:activeTVC animated:NO];
    }
    

    Почему это работает? <Ол>

  • Все изменения ориентации проходят через контроллеры представления, а не представления.

  • Насколько я могу судить, первое представление или подпредставление, которое вы добавляете в свое окно, получает особый соус. Если этот вид имеет контроллер представления, окно выясняет это.

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

    [window addSubview:masterVC.view];
    

    делать что-то вроде этого (не настоящий метод!):

    [window addSubview:masterVC.view withViewController:masterVC];
    

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

    Другие советы

    Очевидно, что если вы добавите view как дочерний элемент viewS, он будет правильно повернут. Это не очень хорошее решение для моего проекта, но похоже, что это может быть единственным обходным путем.

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

    Итак, я заканчиваю настройку ориентации, прежде чем помещать новый контроллер представления в стек, если я знаю, что он изменился:

    [[UIDevice currentDevice] setOrientation:UIInterfaceOrientationPortrait]; 
    

    Да, это неподдерживаемый вызов.

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

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait animated:NO];
    

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

    Это должно сработать.

    - (void)viewDidLoad {
        if (([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeLeft) || 
            ([[UIDevice currentDevice] orientation] == UIDeviceOrientationLandscapeRight)) 
    
        {
            self.view.frame = CGRectMake(0, 0, 1024, 748);
    
        } else {
            self.view.frame = CGRectMake(0, 0, 768, 1004);
        }
    }
    
    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top