SupportInterfaceOrientations не работает

Я хочу, чтобы некоторые из моих пейзажей ViewControllers и некоторый портрет были такими, что я сделал:

Я включил ландшафтный режим:

enter image description here

Затем я добавил эти строки кода в контроллеры представлений, которые я хотел бы видеть:

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationPortrait;
}
-(BOOL)shouldAutorotate
{
    return NO;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

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

Ответ 1

Вот как я это делаю.
Создайте родительский класс UINavigationController.
внутри вас UINavigationController (родительский) переопределяет эти методы, например:

- (NSUInteger)supportedInterfaceOrientations
{
    if([self.topViewController respondsToSelector:@selector(supportedInterfaceOrientationsForThisContorller)])
    {
        return(NSInteger)[self.topViewController performSelector:@selector(supportedInterfaceOrientationsForThisContorller) withObject:nil];
    }
    return UIInterfaceOrientationPortrait;
}

- (BOOL)shouldAutorotate
{
    if([self.visibleViewController respondsToSelector:@selector(shouldAutorotateNow)])
    {
        BOOL autoRotate = (BOOL)[self.visibleViewController
                            performSelector:@selector(shouldAutorotateNow)
                            withObject:nil];
        return autoRotate;

    }
    return NO;
}

Теперь ваш NavigationController должен быть подклассом родительского элемента UINavigationContorller

Swift 3:

Внутри вашего подкласса UINavigationController сделайте это

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        get {
            return self.topViewController?.supportedInterfaceOrientations ?? .all
        }
    }

override var shouldAutorotate: Bool {
        return self.topViewController?.shouldAutorotate ?? false
    }

Обновление Взято от Matt answer, если вы не хотите подкласса:

сначала: сделайте свой viewController делегатом навигационного контроллера в viewDidLoad

self.navigationController?.delegate = self

Затем объявите расширение UIViewController для ответа на метод делегата, как показано ниже:

extension UIViewController: UINavigationControllerDelegate {
    public func navigationControllerSupportedInterfaceOrientations(_ navigationController: UINavigationController) -> UIInterfaceOrientationMask {
        return navigationController.topViewController?.supportedInterfaceOrientations
    }
}

Ответ 2

Разработанный Apple способ сделать это для UINavigationController через UINavigationControllerDelegate.

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

#pragma mark - UINavigationControllerDelegate

- (NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController
{
    return [navigationController.topViewController supportedInterfaceOrientations];
}

По-моему, UINavigationController должен просто по умолчанию использовать описанное выше поведение, но это api Apple предоставил:)

Что касается файла info plist, я сниму все параметры и обрабатываю все это в коде, поскольку это вызвало проблемы для меня в прошлом, и я устал от этого.

Ответ 3

Просто для вас вся информация, создать новый проект, основанный на одном представлении, реализовать команду auto rotate delegate и поддерживаемую ориентацию интерфейса в viewController добавьте в него точку останова.

Запуск (универсальный режим)

  • на симуляторе iphone: выполнение останавливается в точках останова
  • на ipad Simulator: executions НЕ ОСТАНОВИТЬ (методы делегирования никогда не называются!!!!)
  • на устройстве ipad: ok

Так что не тратьте слишком много времени на него, как будто я сделал, XCode 7.3 ОШИБКА

Ответ 5

Находясь под UINavigationController, я реализую UINavigationControllerDelegate и следующий метод:

#pragma mark - From UINavigationControllerDelegate

-(UIInterfaceOrientationMask) navigationControllerSupportedInterfaceOrientations:(UINavigationController*)navigationController {
    return UIInterfaceOrientationMaskPortrait; // TODO: change to whatever you need to allow
}

Ответ 6

Для простоты, для iPad, если свойство Поддерживаемые интерфейсные ориентации (iPad) в info.plist включает все четыре ориентации, при значении свойства UIRequiresFullScreen, равном НЕТ, iOS будет рассматривать ваше приложение как поддерживающее разделенное представление. Если приложение поддерживает функцию разделения просмотра, вы не можете отключить его вращение, по крайней мере, указанными выше способами.


Позвольте углубиться в детали.

Во-первых, нам нужно знать, какие факторы будут влиять на ориентацию экрана:

1. Настройки проекта (info.plist)

Есть два места, где мы можем сделать эту настройку:

  • Project-> Цель → General-> Ориентация устройства

    screen orientation setting in project setting

  • info.plist проекта

    screen orientation setting in info.plist

Два метода одинаковы, и один автоматически синхронизирует другой параметр. В файле info.plist свойство Поддерживаемые ориентации интерфейса (iPad) предназначено для настройки iPad (выберите iPad для раздела "Устройство"), а свойство Поддерживаемые ориентации интерфейса - для iPhone и Univeral (выберите iPhone или "Универсальный" для раздела "Устройство", и эти две настройки всегда будут быть таким же.)

2. Установите поддерживаемые ориентации экрана программно

Существует два способа настройки поддерживаемых ориентаций при кодировании:

  • UIApplicationDelegate supportedInterfaceOrientationsForWindow: метод в UIApplicationDelegate
  • supportedInterfaceOrientations метод UIViewController

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

3. Установить shouldAutorotate свойство в UIViewController

Это свойство доступно только для чтения и используется для контроля, если контроллер представления является вращаемым или нет. Вы можете переопределить свойство в вашем контроллере представления или даже изменить свойство на свойство чтения-записи, чтобы вы могли изменять свойство во время работы приложения. Например:

override public var shouldAutorotate: Bool {
    get {
        return self.shouldAutorotateVariable
    }
    set {
        self.shouldAutorotateVariable = newValue
    }
}

shouldAutorotateVariable является частной собственностью в вашем контроллере представления.

iPhone

Если в shouldAutorotate контроллера shouldAutorotate установлено значение false, iOS пропустит следующие настройки:

  • UIApplicationDelegate supportedInterfaceOrientationsForWindow: метод в UIApplicationDelegate
  • supportedInterfaceOrientations метод UIViewController

iOS будет использовать только настройки проекта (info.plist).

Если свойство shouldAutorotate не переопределено или имеет значение true, то iOS будет использовать общие ориентации, определенные в следующих двух методах:

  • UIApplicationDelegate supportedInterfaceOrientationsForWindow: метод в UIApplicationDelegate
  • supportedInterfaceOrientations метод UIViewController

Если два вышеупомянутых метода не предоставлены, iOS будет использовать настройки проекта (info.plist).

IPad

Начиная с iOS9, iPad поддерживает функцию разделения просмотра. Обратитесь к разделу "Быстрый просмотр" и "Быстрый просмотр" для настройки разделения.

Для простоты, если свойство "Поддерживаемые интерфейсные ориентации (iPad)" в файле info.plist включает все четыре ориентации со значением свойства UIRequiresFullScreen, равным "NO", iOS будет рассматривать ваше приложение как поддерживающее разделенное представление. Если приложение поддерживает разделенное представление, следующие два параметра будут пропущены:

  • UIApplicationDelegate supportedInterfaceOrientationsForWindow: метод в UIApplicationDelegate
  • supportedInterfaceOrientations метод UIViewController

Свойство shouldAutorotate в UIViewController также будет опущено.

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

Если свойство Поддерживаемые интерфейсные ориентации (iPad) в значении info.plist не включает все четыре ориентации, или для свойства UIRequiresFullScreen задано значение YES, приложение не будет поддерживать разделенное представление, а логика управления ориентацией экрана такая же, как в iPhone выше.

Примечание: для настроек проекта (info.plist) лучше установить следующие три свойства непосредственно внутри info.plist:

  • Поддерживаемые ориентации интерфейса (iPad)
  • Поддерживаемые ориентации интерфейса
  • UIRequiresFullScreen

Это сбивает с толку, если вы пытаетесь установить через Project-> Target → General-> Device Orientation: даже если Device установлен как Universe, настройка в iPad все равно вступит в силу.