Поддержка многократных интерфейсных ориентаций

Акселерометры в основанных на iOS устройствах позволяют определить текущую ориентацию устройства. По умолчанию, поддержки приложений и портретные и альбомные ориентации. Когда ориентация основанного на iOS устройства изменяется, система отсылает a UIDeviceOrientationDidChangeNotification уведомление, чтобы позволить любым заинтересованным сторонам знать, что произошло изменение. По умолчанию платформа UIKit прислушивается к этому уведомлению и использует его для обновления интерфейсной ориентации автоматически. Это означает, что только за несколькими исключениями Вы не должны должны быть обрабатывать это уведомление вообще.

../Art/view_orientations_2x.png

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

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

Контроллеры представления, не заполняющие экран обычно, не должны заботиться об ориентации пользовательского интерфейса. Вместо этого заполните область, предоставленную родительским контроллером представления. Корневой контроллер представления (или контроллер представления представил полный экран), более вероятно, будет интересоваться ориентацией устройства.

Управление, какие интерфейсные ориентации поддерживаются (iOS 6)

Когда UIKit получает уведомление ориентации, он использует UIApplication возразите и корневой контроллер представления, чтобы определить, позволяется ли новая ориентация. Если оба объекта соглашаются, что новая ориентация поддерживается, то пользовательский интерфейс повернут к новой ориентации. Иначе ориентация устройства проигнорирована.

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

Объявление представления поддерживаемые интерфейсные ориентации контроллера

Контроллер представления, который действует как корневой контроллер представления главного окна или является представленным полным экраном на главном окне, может объявить, какие ориентации это поддерживает. Это делает это путем переопределения supportedInterfaceOrientations метод. По умолчанию просмотрите контроллеры на устройствах, использующих поддержку идиомы iPad все четыре ориентации. На устройствах, использующих идиому iPhone, все интерфейсные ориентации, но поддерживается перевернутый портрет.

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

Перечисление 8-1 показывает довольно типичную реализацию supportedInterfaceOrientations метод для контроллера представления, поддерживающего портретную ориентацию и оставленную среде ориентацию. Ваша собственная реализация этого метода должна быть столь же простой.

Перечисление 8-1  реализовывая supportedInterfaceOrientations метод

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft;
}

Динамично управление, происходит ли вращение

Иногда можно хотеть динамично отключить автоматическое вращение. Например, когда Вы хотите подавить вращение полностью в течение короткого периода времени, Вы могли бы сделать это. Необходимо временно отключить изменения ориентации, Вы хотите вручную управлять позицией строки состояния (такой как тогда, когда Вы вызываете setStatusBarOrientation:animated: метод).

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

Объявление предпочтительной ориентации представления

Когда контроллер представления представлен полноэкранный для показа его содержания, иногда содержание кажется лучшим, когда просматривается в определенной ориентации в памяти. Если содержание может только быть выведено на экран в той ориентации, то Вы просто возвращаете это как единственную ориентацию от Вашего supportedInterfaceOrientations метод. Если контроллер представления поддерживает многократные ориентации, но кажется лучше в различной ориентации, можно обеспечить предпочтительную ориентацию путем переопределения preferredInterfaceOrientationForPresentation метод. Перечисление 8-2 показывает пример, используемый контроллером представления, содержание которого должно быть представлено в альбомной ориентации. Предпочтительная интерфейсная ориентация должна быть одной из ориентаций, поддерживаемых контроллером представления.

Перечисление 8-2  реализовывая preferredInterfaceOrientationForPresentation метод

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return UIInterfaceOrientationLandscapeLeft;
}

Для более по представлении, посмотрите Контроллеры Представления Представления от Других Контроллеров Представления.

Объявление поддерживаемых интерфейсных ориентаций приложения

Самый простой способ установить поддерживаемые интерфейсные ориентации приложения приложения состоит в том, чтобы отредактировать проект Info.plist файл. Как в случае контроллера представления, Вы определяете, какая из четырех интерфейсных ориентаций разрешена. Для получения дополнительной информации посмотрите информационную Ключевую Ссылку Списка свойств.

Если Вы ограничиваете поддерживаемые ориентации приложения, то те ограничения применяются глобально ко всем контроллерам представления приложения, даже когда Ваше приложение использует системные контроллеры представления. В любой момент времени маска самого верхнего контроллера представления логически ANDредактор с маской приложения для определения то, какие ориентации разрешены. Результат этого вычисления никогда не должен быть 0. Если это, система бросает a UIApplicationInvalidInterfaceOrientationException исключение.

Поскольку маска приложения применяется глобально, используйте ее экономно.

Понимание Процесса Вращения (iOS 5 и ранее)

На iOS 5 и ранее, контроллер представления может иногда участвовать в процессе вращения, даже когда это не самый верхний полноэкранный контроллер представления. Когда контейнерный контроллер представления просит у своих дочерних элементов их поддерживаемые интерфейсные ориентации, это обычно происходит. На практике возможность к дочерним элементам переопределить родителей редко полезна. С этим в памяти, необходимо рассмотреть эмуляцию поведения iOS 6 как можно больше в приложении, которое должно также поддерживать iOS 5:

Объявление поддерживаемых интерфейсных ориентаций

Для объявления поддерживаемых интерфейсных ориентаций переопределите shouldAutorotateToInterfaceOrientation: метод и указывает, какие ориентации Ваше представление поддерживает. Необходимо всегда выбирать ориентации поддержки представления во время проектирования и реализовывать код с теми ориентациями в памяти. Нет никакого преимущества к выбору, какие ориентации Вы хотите поддерживать динамично на основе информации о выполнении. Даже если бы Вы сделали так, то необходимо было бы все еще реализовать необходимый код для поддержки всех возможных ориентаций, и таким образом, Вы могли бы также просто принять решение поддерживать ориентацию или не переднюю сторону.

Перечисление 8-3 показывает довольно типичную реализацию shouldAutorotateToInterfaceOrientation: метод для контроллера представления, поддерживающего портретную ориентацию по умолчанию и оставленную среде ориентацию. Ваша собственная реализация этого метода должна быть столь же простой.

Перечисление 8-3  реализовывая shouldAutorotateToInterfaceOrientation: метод

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
   if ((orientation == UIInterfaceOrientationPortrait) ||
       (orientation == UIInterfaceOrientationLandscapeLeft))
      return YES;
 
   return NO;
}

Если Ваши поддержки приложений обе альбомных ориентации, можно использовать UIInterfaceOrientationIsLandscape макрос как ярлык, вместо того, чтобы явно сравнить параметр ориентации с обеими альбомными константами. Платформа UIKit так же определяет a UIInterfaceOrientationIsPortrait макрос для идентификации обоих вариантов портретной ориентации.

Реакция на изменения ориентации в видимом контроллере представления

Когда вращение происходит, контроллеры представления играют неотъемлемую роль процесса. Видимые контроллеры представления уведомляются на различных этапах вращения, чтобы дать им шанс выполнить дополнительные задачи. Вы могли бы использовать эти методы, чтобы скрыть или показать представления, изменить местоположение или изменить размеры представлений или уведомить другие части Вашего приложения об изменении ориентации. Поскольку Ваши пользовательские методы вызывают во время работы вращения, необходимо избежать выполнять любые длительные операции там. Необходимо также избежать заменять всю иерархию представления новым набором представлений. Существуют лучшие способы обеспечить уникальные представления для различных ориентаций, таких как представление нового контроллера представления (как описано в Создании Альтернативного Альбомного Интерфейса).

Методы вращения отправляются в корневой контроллер представления. Корневой контроллер представления передает эти события по мере необходимости его дочерним элементам, и т.д. вниз иерархия контроллера представления. Вот последовательность событий, происходящих, когда инициировано вращение:

  1. Окно вызывает корневой контроллер представления willRotateToInterfaceOrientation:duration: метод.

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

  2. Окно корректирует границы представления контроллера представления. Это вызывает представление к расположению его подпредставления, инициировав контроллер представления viewWillLayoutSubviews метод. Когда этот метод работает, можно запросить объект приложения statusBarOrientation свойство для определения текущего макета интерфейса пользователя.

    Посмотрите, как контроллеры представления участвуют в процессе создания макета представления.

  3. Контроллер представления willAnimateRotationToInterfaceOrientation:duration: метод вызывают. Этот метод вызывают из блока анимации так, чтобы любые изменения свойства, которые Вы вносите, были анимированы в то же время, что и другие анимации, включающие вращение.

  4. Анимация выполняется.

  5. Окно вызывает контроллер представления didRotateFromInterfaceOrientation: метод.

    Контейнерные контроллеры представления передают это сообщение к в настоящее время выводимый на экран довольный контроллеры представления. Это действие отмечает конец процесса вращения. Можно использовать этот метод, чтобы показать представления, изменить расположение представлений или внести другие изменения в приложение.

Рисунок 8-1 показывает визуальное представление предыдущих шагов. Это также показывает, как интерфейс смотрит на различные этапы процесса.

Рисунок 8-1  , Обрабатывающий интерфейсное вращение

Когда Ваш контроллер представления скрыт, вращения могут произойти

Если Ваше содержание контроллера представления не является экранным, когда вращение происходит, то оно не видит список сообщений вращения. Например, рассмотрите следующую последовательность событий:

  1. Ваш контроллер представления представляет другой полный экран содержания контроллера представления.

  2. Пользователь поворачивает устройство так, чтобы изменилась ориентация пользовательского интерфейса.

  3. Ваше приложение отклоняет представленный контроллер представления.

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

Создание альтернативного альбомного интерфейса

Если Вы хотите представить те же данные по-другому на основе того, является ли устройство в портретной или альбомной ориентации, способ сделать так использует два отдельных контроллера представления. Один контроллер представления должен управлять дисплеем данных в основной ориентации (обычно портрет), в то время как другой управляет дисплеем данных в альтернативной ориентации. Используя два представления контроллеры более просто и более эффективен, чем внесение существенных изменений в Вашу иерархию представления каждый раз изменения ориентации. Это позволяет каждому контроллеру представления фокусироваться на представлении данных в одной ориентации и управлять вещами соответственно. Это также избавляет от необходимости замусорить Ваш код контроллера представления условными проверками на текущую ориентацию.

Для поддержки альтернативного альбомного интерфейса необходимо сделать следующее:

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

Перечисление 8-4 показывает ключевые методы, которые необходимо реализовать в основном контроллере представления, поддерживающем портретную ориентацию. Когда основной контроллер представления загружается из раскадровки, он регистрируется для получения измененных на ориентацию уведомлений из совместно используемого UIDevice объект. Когда такое уведомление поступает, orientationChanged: метод тогда представляет или отклоняет альбомный контроллер представления в зависимости от текущей ориентации.

Перечисление 8-4  , Представляющее альбомный контроллер представления

@implementation PortraitViewController
- (void)awakeFromNib
{
    isShowingLandscapeView = NO;
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self
                                 selector:@selector(orientationChanged:)
                                 name:UIDeviceOrientationDidChangeNotification
                                 object:nil];
}
 
- (void)orientationChanged:(NSNotification *)notification
{
    UIDeviceOrientation deviceOrientation = [UIDevice currentDevice].orientation;
    if (UIDeviceOrientationIsLandscape(deviceOrientation) &&
        !isShowingLandscapeView)
    {
        [self performSegueWithIdentifier:@"DisplayAlternateView" sender:self];
        isShowingLandscapeView = YES;
    }
    else if (UIDeviceOrientationIsPortrait(deviceOrientation) &&
             isShowingLandscapeView)
    {
        [self dismissViewControllerAnimated:YES completion:nil];
        isShowingLandscapeView = NO;
    }
}

Подсказки для реализации Вашего кода вращения

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