Поддерживаемые ориентации интерфейса в info.plist, кажется, блокируют вызовы shouldAutorotate - PullRequest
0 голосов
/ 07 октября 2019

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

Я могу установить допустимые ориентации устройств в проекте Xcode, и это, кажется, создает пару элементов массива вinfo.plist проекта: «Поддерживаемые ориентации интерфейса (iPad)» и «Поддерживаемые ориентации интерфейса (iPhone)», в которых перечислены допустимые ориентации для каждого типа устройства. Присутствие этих элементов делает переходы с экрана запуска гладкими, как шелк, во всех ориентациях.

Я могу включить / отключить автоповорот, переопределив shouldAutorotate в моем контроллере корневого представления (на данный момент только один контроллер). Проблема заключается в том, что наличие элементов поддерживаемого интерфейса в файле info.plist, по-видимому, подавляет все вызовы shouldAutorotate, в результате чего управление автоповоротом становится неработоспособным.

class   RootController: UIViewController
  {
    var allowAutorotation = true    //  My autorotation switch.
      { didSet    { guard   allowAutorotation   else  { return }
                    UIViewController.attemptRotationToDeviceOrientation()
                    /*  Do other stuff.   */ }   }

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask
      { NSLog ("RootController: supportedInterfaceOrientations")
        return .allButUpsideDown  }

    override var shouldAutorotate: Bool
      { NSLog ("RootController: shouldAutorotate")
        return allowAutorotation  }

    override func viewDidLoad()
      { allowAutorotation = true
        super.viewDidLoad()  }

         }

Я использую viewDidLoad для вызова tryRotationToDeviceOrientation () как можно раньше. Если я этого не сделаю, экран приложения появится в книжной ориентации, даже если устройство находится в альбомной ориентации. (Для Portrait это правильно, но Portrait не правильно.) Я пытался сделать аналогичный вызов из других мест, включая didFinishLaunchingWithOptions в делегате приложения, который, я думаю, может быть наиболее логичным для него, но это не так. Кажется, это не имеет значения.

Если я удаляю элементы Поддерживаемой ориентации из info.plist и определяю разрешенные ориентации в коде, как показано, я могу видеть из моих контрольных сигналов NSLog, что вызовы shouldAutorotate происходят в соответствующие моментыНо запуск тогда выглядит немного неловко в пейзаже. На экране запуска строка состояния ориентирована неправильно: вдоль одного из вертикальных краев, а не вверху, и когда происходит переход к экрану приложения, она обычно исчезает на расстоянии 10-20 ° от горизонтали. Он мгновенно переходит в горизонтальное положение (на самом деле он настолько быстрый, что иногда его трудно увидеть), и строка состояния в этом случае правильно вверху, и с этого момента все выглядит хорошо, но эффект все еще кажется немного непрофессиональным.

Так как это происходит только на мгновение и только один раз при запуске, я полагаю, что смогу с этим смириться (я не могу жить без элемента управления авторотацией), но я надеялся, что кто-то может предложить способ получения вызовов beforeAutorotate дляработать даже с ориентациями, определенными в info.plist. Или, может быть, какая-то другая стратегия?

1 Ответ

0 голосов
/ 24 октября 2019

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

class RootController: UIViewController  {

private var appIsLaunching = true  //  Set false when app first becomes active. Never set true again.

func appDidBecomeActive()
  { if appIsLaunching  { appIsLaunching = false; CATransaction.setDisableActions (false) } } 

override func viewWillTransition (to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator)
  { if appIsLaunching  { CATransaction.setDisableActions (true) } 
    super.viewWillTransition (to: size, with: coordinator) }

        }

А в appDelegate:

func applicationDidBecomeActive ( _ application: UIApplication )
  { let root = window!.rootViewController as! RootController; root.appDidBecomeActive() }

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

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

...