Вопрос:

Как заставить просмотр ориентации контроллера в iOS 8?

ios objective-c ios8 uinavigationcontroller

137144 просмотра

25 ответа

2765 Репутация автора

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

[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];

Но это не работает в iOS 8. Кроме того, я видел некоторые ответы в переполнении стека, где люди предлагали, чтобы мы всегда избегали этого подхода с iOS 8 и далее.

Чтобы быть более конкретным, мое приложение является универсальным типом приложения. Всего три контроллера.

  1. Контроллер First View - он должен поддерживать все ориентации в iPad и только портрет (кнопка «Домой» вниз) в iPhone.

  2. Контроллер второго вида - он должен поддерживать только ландшафтное право в любых условиях

  3. Контроллер третьего вида - он должен поддерживать только ландшафтное право в любых условиях

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

Ниже мой shouldAutorotateи supportedInterfaceOrientationsметоды во втором и третьем представлении контроллера.

-(NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(BOOL)shouldAutorotate {
    return NO;
}

Есть ли какое-либо решение для этого или какой-либо лучший способ блокировки контроллера представления в определенной ориентации для iOS 8. Пожалуйста, помогите!

Автор: Rashmi Ranjan mallick Источник Размещён: 14.10.2014 09:26

Ответы (25)


298 плюса

10680 Репутация автора

Решение

Для iOS 7 - 10:

Objective-C:

[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];

Свифт 3:

let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()

Просто позвоните в - viewDidAppear:представленный контроллер представления.

Автор: Sunny Shah Размещён: 14.10.2014 10:11

91 плюса

2031 Репутация автора

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

Я использую следующие 2 расширения для UINavigationController и UITabBarController, чтобы контроллеры представления, встроенные в один из этих контроллеров, могли принимать решения.

Дайте View Controllers мощь!

Swift 2.3

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> Int {
        return visibleViewController.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

extension UITabBarController {
    public override func supportedInterfaceOrientations() -> Int {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Свифт 3

extension UINavigationController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
    }
}

extension UITabBarController {
    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations
        }
        return super.supportedInterfaceOrientations
    }

    open override var shouldAutorotate: Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate
        }
        return super.shouldAutorotate
    }
}

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

Отключить вращение

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

Блокировка для определенной ориентации

class ViewController: UIViewController {
    override func supportedInterfaceOrientations() -> Int {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
}

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

Блокировка поворота экрана

Автор: Korey Hinton Размещён: 29.01.2015 05:13

9 плюса

764 Репутация автора

Это должно работать с iOS 6 и выше, но я протестировал его только на iOS 8. Подкласс UINavigationControllerи переопределить следующие методы:

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (BOOL)shouldAutorotate {
    return NO;
}

Или спроси видимый контроллер вида

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}

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

и реализовать методы там.

Автор: Mojo66 Размещён: 31.01.2015 03:24

3 плюса

636 Репутация автора

Комбинация ответов Сидса и Корейса сработала для меня.

Расширение контроллера навигации:

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return visibleViewController.shouldAutorotate()
    }
}

Затем отключение вращения на одном просмотре

class ViewController: UIViewController {
    override func shouldAutorotate() -> Bool {
        return false
    }
}

И вращение в соответствующую ориентацию перед началом

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if (segue.identifier == "SomeSegue")
    {
        let value = UIInterfaceOrientation.Portrait.rawValue;
        UIDevice.currentDevice().setValue(value, forKey: "orientation")
    }
}
Автор: Misha Размещён: 02.03.2015 05:59

20 плюса

436 Репутация автора

Я обнаружил, что если это представленный контроллер представления, вы можете переопределить preferredInterfaceOrientationForPresentation

Swift:

override func supportedInterfaceOrientations() -> Int {
  return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
  return UIInterfaceOrientation.LandscapeLeft
}

override func shouldAutorotate() -> Bool {
  return false
}
Автор: Zipme Размещён: 18.03.2015 07:38

23 плюса

1203 Репутация автора

Вот что сработало для меня:

https://developer.apple.com/library//ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/clm/UIViewController/attemptRotationToDeviceOrientation

Вызовите это в вашем viewDidAppear: метод.

- (void) viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    [UIViewController attemptRotationToDeviceOrientation];
}
Автор: Vincil Bishop Размещён: 18.03.2015 04:52

2 плюса

1822 Репутация автора

Верхнее решение выше:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

не работал для меня, когда я вызвал его в viewDidAppear представленного контроллера представления. Однако это сработало, когда я назвал его в preparForSegue в представляемом контроллере представления.

(Извините, репутации недостаточно, чтобы комментировать это решение, поэтому мне пришлось добавить его вот так)

Автор: guido Размещён: 07.05.2015 09:59

9 плюса

30979 Репутация автора

Это отзыв на комментарии в ответе Сида Шаха , касающиеся того, как отключить анимацию с помощью:

[UIView setAnimationsEnabled:enabled];

Код:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:NO];
    [UIView setAnimationsEnabled:NO];

    // Stackoverflow #26357162 to force orientation
    NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
    [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:NO];
    [UIView setAnimationsEnabled:YES];
}
Автор: ohho Размещён: 28.07.2015 02:49

0 плюса

3841 Репутация автора

У меня та же проблема, и я трачу на нее столько времени. Так что теперь у меня есть свое решение. Моя настройка приложения поддерживает только портретную ориентацию. Однако некоторые экраны в моем приложении должны иметь только альбомную ориентацию. Я исправляю это с помощью переменной isShouldRotate в AppDelegate . И функция в AppDelegate :

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    if isShouldRotate == true {
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

И, наконец, когда ViewControllerA требуется ландшафтное состояние. Просто сделать это: перед тем толчком / представить , чтобы ViewControllerA назначить isShouldRotate к истинному . Не забывайте, когда выдвигаете / отклоняете этот контроллер, присваивайте isShouldRotate значение false при viewWillDisappear .

Автор: lee Размещён: 28.08.2015 03:44

6 плюса

736 Репутация автора

Если вы используете navigationViewController, вы должны создать для этого собственный суперкласс и переопределить:

- (BOOL)shouldAutorotate {
  id currentViewController = self.topViewController;

  if ([currentViewController isKindOfClass:[SecondViewController class]])
    return NO;

  return YES;
}

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

Предположим, что вы используете раскадровку. Вы должны создать ручной переход ( How to ) и в своем методе «onClick»:

- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
  NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
  [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
  [self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}

Это заставит альбомную ориентацию до того, как ваш суперкласс отключит функцию автоматического поворота.

Автор: Lau Размещён: 10.09.2015 07:59

0 плюса

8422 Репутация автора

According to solution showed by @sid-sha you have to put everything in the viewDidAppear: method, otherwise you will not get the didRotateFromInterfaceOrientation: fired, so something like:

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
        interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
        [[UIDevice currentDevice] setValue:value forKey:@"orientation"];
    }
}
Автор: loretoparisi Размещён: 30.09.2015 03:01

15 плюса

24329 Репутация автора

Этот способ работает для меня в Swift 2 iOS 8.x:

PS (этот метод не требует переопределения функций ориентации, таких как mustautorotate на каждом viewController, только один метод на AppDelegate)

Отметьте «требуется полный экран» в общей информации о вашем проекте. введите описание изображения здесь

Итак, на AppDelegate.swift сделайте переменную:

var enableAllOrientation = false

Итак, поместите также эту функцию:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
        if (enableAllOrientation == true){
            return UIInterfaceOrientationMask.All
        }
        return UIInterfaceOrientationMask.Portrait
}

Итак, в каждом классе вашего проекта вы можете установить эту переменную в viewWillAppear:

override func viewWillAppear(animated: Bool)
{
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appDelegate.enableAllOrientation = true
}

Если вам нужно сделать выбор в зависимости от типа устройства, вы можете сделать это:

override func viewWillAppear(animated: Bool)
    {
        super.viewWillAppear(animated)
        let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        switch UIDevice.currentDevice().userInterfaceIdiom {
        case .Phone:
        // It's an iPhone
           print(" - Only portrait mode to iPhone")
           appDelegate.enableAllOrientation = false
        case .Pad:
        // It's an iPad
           print(" - All orientation mode enabled on iPad")
           appDelegate.enableAllOrientation = true
        case .Unspecified:
        // Uh, oh! What could it be?
           appDelegate.enableAllOrientation = false
        }
    }
Автор: Alessandro Ornano Размещён: 19.01.2016 04:03

1 плюс

4352 Репутация автора

According to Korey Hinton's answer

Swift 2.2:

extension UINavigationController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return visibleViewController!.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        return visibleViewController!.shouldAutorotate()
    }
}


extension UITabBarController {
    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        if let selected = selectedViewController {
            return selected.supportedInterfaceOrientations()
        }
        return super.supportedInterfaceOrientations()
    }
    public override func shouldAutorotate() -> Bool {
        if let selected = selectedViewController {
            return selected.shouldAutorotate()
        }
        return super.shouldAutorotate()
    }
}

Disable Rotation

override func shouldAutorotate() -> Bool {
    return false
}

Lock to Specific Orientation

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}
Автор: phnmnn Размещён: 06.04.2016 11:41

2 плюса

442 Репутация автора

Мои требования

  1. заблокировать все виды в портретном режиме
  2. использовать AVPlayerViewControllerдля воспроизведения видео

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

Сначала определите supportedInterfaceOrientationsForWindowвAppDelegate.swift

var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if portrait {
        return .Portrait
    } else {
        return .Landscape
    }
}

Во-вторых, в вашем главном контроллере представления определите следующие функции

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    print("\(#function)")
    return .Portrait
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return .Portrait
}

override func shouldAutorotate() -> Bool {
    return false
}

Затем вам нужно подкласс AVPlayerViewController

class MyPlayerViewController: AVPlayerViewController {

    var size: CGSize?

    var supportedOrientationMask: UIInterfaceOrientationMask?
    var preferredOrientation: UIInterfaceOrientation?

    override func viewDidLoad() {
        super.viewDidLoad()

        if let size = size {
            if size.width > size.height {
                self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
                self.preferredOrientation =.LandscapeRight
            } else {
                self.supportedOrientationMask =.Portrait
                self.preferredOrientation =.Portrait
            }
        }
    }

Переопределите эти три функции в MyPlayerViewController.swift

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return self.supportedOrientationMask!
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
    return self.preferredOrientation!
}

Поскольку пользователь может поворачивать устройство влево или вправо, нам нужно установить автоматический поворот на true

override func shouldAutorotate() -> Bool {
    return true
}

Наконец, создайте MyPlayerViewControllerэкземпляр в вашем контроллере представления и установите значение размера свойства.

let playerViewController = MyPlayerViewController()

// Get the thumbnail  
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)

let size = thumbnail?.size
playerViewController.size = size

Начните свой игрок с должным videoUrl, затем назначьте своего игрока playerViewController. Удачного кодирования!

Автор: charles.cc.hsu Размещён: 11.04.2016 03:47

0 плюса

4790 Репутация автора

My solution

In AppDelegate:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    if let topController = UIViewController.topMostViewController() {
        if topController is XXViewController {
            return [.Portrait, .LandscapeLeft]
        }
    }
    return [.Portrait]
}

XXViewController is the ViewController you want to support Landscape mode.

Then Sunny Shah's solution would work in your XXViewController on any iOS version:

let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")

This is the utility function to find the top most ViewController.

extension UIViewController {

    /// Returns the current application's top most view controller.
    public class func topMostViewController() -> UIViewController? {
        let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
        return self.topMostViewControllerOfViewController(rootViewController)
    }



    /// Returns the top most view controller from given view controller's stack.
    class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
        // UITabBarController
        if let tabBarController = viewController as? UITabBarController,
           let selectedViewController = tabBarController.selectedViewController {
            return self.topMostViewControllerOfViewController(selectedViewController)
        }

        // UINavigationController
        if let navigationController = viewController as? UINavigationController,
           let visibleViewController = navigationController.visibleViewController {
            return self.topMostViewControllerOfViewController(visibleViewController)
        }

        // presented view controller
        if let presentedViewController = viewController?.presentedViewController {
            return self.topMostViewControllerOfViewController(presentedViewController)
        }

        // child view controller
        for subview in viewController?.view?.subviews ?? [] {
            if let childViewController = subview.nextResponder() as? UIViewController {
                return self.topMostViewControllerOfViewController(childViewController)
            }
        }

        return viewController
    }

}
Автор: duan Размещён: 22.06.2016 08:07

4 плюса

1619 Репутация автора

Я перепробовал много решений, но одно из них работало так:

Там нет необходимости редактировать info.plistв IOS 8 и 9.

- (BOOL) shouldAutorotate {
    return NO;
}   

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}

Возможные ориентации из документации Apple :

UIInterfaceOrientationUnknown

Ориентация устройства не может быть определена.

UIInterfaceOrientationPortrait

Устройство находится в портретном режиме, устройство находится в вертикальном положении, а кнопка «Домой» находится внизу.

UIInterfaceOrientationPortraitUpsideDown

Устройство находится в портретном режиме, но перевернуто, устройство находится в вертикальном положении, а кнопка «Домой» вверху.

UIInterfaceOrientationLandscapeLeft

Устройство находится в альбомной ориентации, устройство находится в вертикальном положении, а кнопка «Домой» находится на левой стороне.

UIInterfaceOrientationLandscapeRight

Устройство находится в альбомной ориентации, устройство находится в вертикальном положении, а кнопка «Домой» находится на правой стороне.

Автор: hoogw Размещён: 05.07.2016 10:34

6 плюса

605 Репутация автора

По Xcode 8методам преобразуются в свойства, поэтому работает следующее Swift:

override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

override public var shouldAutorotate: Bool {
    return true
}
Автор: Ali Momen Sani Размещён: 21.09.2016 12:49

0 плюса

36 Репутация автора

Используйте это для блокировки ориентации контроллера вида, протестированного на IOS 9:

// Закрепить ориентацию вправо

-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscapeRight;
}

-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
    return UIInterfaceOrientationMaskLandscapeRight;
}
Автор: robegamesios Размещён: 18.10.2016 05:57

0 плюса

41 Репутация автора

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

- (void) viewWillAppear:(BOOL)animated
{
    [UIViewController attemptRotationToDeviceOrientation];
}

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

-(BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskLandscapeLeft;
}

В этом примере вам также необходимо установить для разрешенных ориентаций устройства значение «Пейзаж влево» в настройках проекта (или непосредственно в нем info.plist). Просто измените конкретную ориентацию, которую вы хотите использовать, если вы хотите что-то другое, чемLandscapeLeft.

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

Автор: ViperMav Размещён: 13.02.2017 02:22

1 плюс

8194 Репутация автора

I tried a few solutions in here and the important thing to understand is that it's the root view controller that will determine if it will rotate or not.

I created the following objective-c project github.com/GabLeRoux/RotationLockInTabbedViewChild with a working example of a TabbedViewController where one child view is allowed rotating and the other child view is locked in portrait.

It's not perfect but it works and the same idea should work for other kind of root views such as NavigationViewController. :)

Дочернее представление блокирует родительскую ориентацию

Автор: GabLeRoux Размещён: 22.08.2017 06:13

10 плюса

7083 Репутация автора

Прежде всего - это плохая идея, в общем, что-то не так с архитектурой вашего приложения, но sh..t happens, если это так, вы можете попробовать сделать что-то вроде ниже:

final class OrientationController {

    static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]

    // MARK: - Public

    class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
        OrientationController.allowedOrientation = [orientationIdiom]
    }

    class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
        var mask:UIInterfaceOrientationMask = []
        switch orientation {
            case .unknown:
                mask = [.all]
            case .portrait:
                mask = [.portrait]
            case .portraitUpsideDown:
                mask = [.portraitUpsideDown]
            case .landscapeLeft:
                mask = [.landscapeLeft]
            case .landscapeRight:
                mask = [.landscapeRight]
        }

        OrientationController.lockOrientation(mask)

        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
    }
}

Чем в AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    // do stuff
    OrientationController.lockOrientation(.portrait)
    return true
}

// MARK: - Orientation

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return OrientationController.allowedOrientation
}

И всякий раз, когда вы хотите изменить ориентацию, делайте так:

OrientationController.forceLockOrientation(.landscapeRight)

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

OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)

Это все

Автор: gbk Размещён: 03.09.2017 04:54

2 плюса

557 Репутация автора

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    [UIViewController attemptRotationToDeviceOrientation];
}
Автор: Roman Solodyashkin Размещён: 20.09.2017 11:04

2 плюса

31 Репутация автора

[iOS9+] If anyone dragged all the way down here as none of above solutions worked, and if you present the view you want to change orientation by segue, you might wanna check this.

Check your segue's presentation type. Mine was 'over current context'. When I changed it to Fullscreen, it worked.

Thanks to @GabLeRoux, I found this solution.

  • This changes only works when combined with solutions above.
Автор: Goh Размещён: 27.09.2017 10:20

0 плюса

301 Репутация автора

Для меня VC верхнего уровня необходим для реализации переопределения ориентации. Использование VC вниз по стеку не будет иметь никакого эффекта, если верхний VC не реализует.

VC-main
    |
    -> VC 2
        |
        -> VC 3

Только VC-Main прослушивается, по сути, в моем тестировании.

Автор: bduhbya Размещён: 26.01.2018 07:37

0 плюса

2245 Репутация автора

Похоже, что даже ты здесь так много ответов, никого не было достаточно для меня. Я хотел форсировать ориентацию, а затем при возвращении вернуться к ориентации устройства, но [UIViewController attemptRotationToDeviceOrientation];просто не сработало. Что также усложнило, так это то, что я добавил shouldAutorotate в false, основываясь на каком-то ответе, и не смог получить желаемых эффектов для правильного поворота назад во всех сценариях.

Вот что я сделал:

Перед нажатием контроллера в вызове в его конструкторе инициализации это:

_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
                               name:UIDeviceOrientationDidChangeNotification];

Поэтому я сохраняю последнюю ориентацию устройства и регистрируюсь на событие изменения ориентации. Событие смены ориентации простое:

- (void)rotated:(NSNotification*)notification {
    _userOrientation = UIDevice.currentDevice.orientation;
}

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

- (void)onViewDismissing {
    super.onViewDismissing;
    [UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
    [UIViewController attemptRotationToDeviceOrientation];
}

И это должно быть там тоже:

- (BOOL)shouldAutorotate {
    return true;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

А также навигационный контроллер должен делегировать shouldAutorotate и supportInterfaceOrientations, но, как я полагаю, большинство людей уже имеют.

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

Автор: Renetik Размещён: 13.06.2019 06:14
Вопросы из категории :
32x32