2016-11-09 15 views
1

Я хочу заблокировать ориентацию во всех ViewControllers до портрета, за исключением одного из них, когда он всегда выдвигается в положение landscapeRight. Я пробовал много решений, используя расширения для UINavigationController, переопределяя supportedInterfaceOrientations и shouldAutorotate, но не повезло.Блокировка только одной ориентации ViewController к ландшафту, а остальное - к портфолио

ответ

2

Я нашел решение, которое на данный момент работает.

  1. На каждом контроллере представления вы должны поместить этот код для поддержки только нужный поворот (landscapeRight в примере):

    override var shouldAutorotate: Bool { 
        return true 
    } 
    
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 
        return UIInterfaceOrientationMask.landscapeRight 
    } 
    
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { 
        return .landscapeRight 
    } 
    

    С другой стороны реализовать те же методы, но с портретной ориентации.

  2. Создать расширение для UINavigationController

    open override var supportedInterfaceOrientations: UIInterfaceOrientationMask { 
        return (self.topViewController?.supportedInterfaceOrientations)! 
    } 
    
    open override var shouldAutorotate: Bool { 
        return true 
    } 
    

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

Единственный контроллер, который я хотел показать в ландшафтном режиме, который я представил модально.

1

Вы столкнетесь с путаницей, если используете навигационный контроллер для представления представлений. Например, мы обычно используем контроллер навигации для обработки добавлений видов, вызывая функции экземпляра контроллера навигации, такие как performSegueWithIdentifier:sender: или pushViewController:animated:.

Pushing не будет работать так, как вы этого хотите.

И segues, вероятно, тоже не сработает, особенно если в IB вы создали segue с контроллера навигации!

В любом случае, если вам удалось переопределить ориентацию навигационного контроллера «родителя», вы рискуете столкнуться с краевыми случаями вниз по линии, и вы, вероятно, используете что-то отрывочное, что может потерять поддержку при любом обновлении.

Тем не менее, обходной путь я нашел:

Шаг 1

Используйте presentViewController:animated:completion: представить landscapeRight контроллер представления:

// assuming you're using IB and Main bundle 
let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil) 
let landscapeViewController = storyboard.instantiateViewController(withIdentifier: "LandscapeViewControllerStoryboardID") 
self.present(landscapeViewController, animated: true, completion: { 
    print("landscapeViewController presented") 
}) 

Шаг 2

Добавление следующее переопределение на ваш landscapeViewController фактически работает сейчас:

/* override the preferredInterfaceOrientationForPresentation for a view controller 
that is intended to be presented full screen in a specific orientation. 
https://developer.apple.com/reference/uikit/uiviewcontroller */ 
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { 
    return .landscapeRight 
} 

Шаг 3 (Необязательно)

При всей этой работе, есть еще некоторые странности, когда вы закроете свой landscapeViewController: Он находится в альбомной ориентации и сейчас.

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

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

let ratio = self.view.bounds.width/self.view.bounds.height 
if (ratio > 1) { // horizontal/landscape 
    self.currentOrientationIsPortrait = false // read by navigation controller when dismissing full screen view player 
} else { 
    self.currentOrientationIsPortrait = true // read by navigation controller when dismissing full screen view player 
} 

Затем я проверить значение этого экземпляра вида контроллера в моем navigationController класса преимущественная ориентация переопределение. Допустим, контроллер представления, из которых я представляю landscapeViewController называется presentingViewController:

// execution order: during visibileViewController's dismissal 
override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { 
    get { 

     if visibleViewController != nil { 

      // check if landscapeViewController is being dismissed 
      if (visibleViewController as? LandscapeViewController) != nil { 

       // check if the top view controller is one that tracks its orientation (currently only presentingViewController) 
       if let presentingViewController = self.viewControllers.last as? PresentingViewController { 

        if presentingViewController.currentOrientationIsPortrait { 
         return .portrait // TODO should we not support portraitUpsideDown? 
        } 
       } 
      } 
      // otherwise, return whatever 
      return visibleViewController!.preferredInterfaceOrientationForPresentation 
     } 
     // otherwise, return whatever 
     return super.preferredInterfaceOrientationForPresentation 
    } 
} 

И, лото. (Надеюсь)

EDIT

Также не забудьте поставить этот код в других ViewControllers:

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation { 
    return .portrait 
} 
+1

Спасибо за ваши усилия. Да, это работает только с одним редактированием (отредактирован ответ). Спасибо. – Slavcho

+0

Спасибо @ Славчо! – Rob

 Смежные вопросы

  • Нет связанных вопросов^_^