Как заблокировать ориентацию только для одного контроллера представления?

Могу ли я установить портретную ориентацию и заблокировать ориентацию только в одном контроллере?

Я пробовал:

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

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

но мне это не помогает. Должен ли я добавить что-нибудь еще?


person Orkhan Alizade    schedule 29.04.2015    source источник


Ответы (6)


Этот код должен работать:

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

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

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

Если теперь он работает для вас, то я полагаю, что ваш контроллер находится в каком-то другом контроллере (UINavigationController, UITabBarController, UISplitViewController). В этом случае вам нужно использовать этот код в родительском контроллере.

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

class NavigationController: UINavigationController {

    var shouldRotate: Bool = true

    override func supportedInterfaceOrientations() -> Int {
        return shouldRotate ? Int(UIInterfaceOrientationMask.Portrait.rawValue) : Int(UIInterfaceOrientationMask.All.rawValue)
    }

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

Затем в контроллере, который вам нужно отключить ориентацию, вы можете отключить его для своего навигационного контроллера:

class ViewController: UIViewController {

    var lastControllerRotationStatus: Bool?

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        if let navigationController = self.navigationController as? NavigationController {
            lastControllerRotationStatus = navigationController.shouldRotate
            navigationController.shouldRotate = false
        }
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)

        if let navigationController = self.navigationController as? NavigationController {
            navigationController.shouldRotate = lastControllerRotationStatus ?? true
        }
    }
}

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

Тот же подход с настройкой переменной из контроллера, который вы можете использовать для управления вращением из AppDelegate метода application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int

Тогда вам не нужно наследовать от контроллера навигации.

Ваш AppDelegate код класса будет выглядеть так:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    var shouldRotate = true
    func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {

        return shouldRotate ? Int(UIInterfaceOrientationMask.All.rawValue) : Int(UIInterfaceOrientationMask.Portrait.rawValue)

    }

}

И код вашего контроллера будет выглядеть так:

class ViewController: UIViewController {

    var lastControllerRotationStatus: Bool?

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            lastControllerRotationStatus = appDelegate.shouldRotate
            appDelegate.shouldRotate = false
        }
    }

    override func viewDidDisappear(animated: Bool) {
        super.viewDidDisappear(animated)

        if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate {
            appDelegate.shouldRotate = lastControllerRotationStatus ?? true
        }
    }
}
person Vasyl Khmil    schedule 29.04.2015
comment
опять не работает. Мой viewController находится в NavigationController, но у него (NavigationController) есть много других viewController, и он мне нужен только в одном контроллере - person Orkhan Alizade; 29.04.2015
comment
@OrkhanAlizade ответил - person Vasyl Khmil; 29.04.2015
comment
NavigationController ошибка Use of undeclarated type NavigationController - person Orkhan Alizade; 29.04.2015
comment
@OrkhanAlizade вам нужно унаследовать UINavigationController. Класс NavigationController унаследован от UINavigationController - person Vasyl Khmil; 29.04.2015
comment
вот так class InfoController: UIViewController, UINavigationController или? Это снова не работает - person Orkhan Alizade; 29.04.2015
comment
@OrkhanAlizade, пожалуйста, проверьте код для AppDelegate. Это другое решение, и его легче понять. - person Vasyl Khmil; 29.04.2015
comment
Позвольте нам продолжить это обсуждение в чате. - person Orkhan Alizade; 29.04.2015

Если вам нужна книжная ориентация, но вы хотите заблокировать только один viewController (например, в альбомной ориентации), вы можете сделать это следующим образом:

У меня это сработало со Swift 2.0

AppDelegate

var shouldRotate = true

//MARK: - Func to rotate only one view controller
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {

    if (shouldRotate == true){
        return UIInterfaceOrientationMask.All
    }

    return UIInterfaceOrientationMask.Landscape

}

ViewController

    override func viewDidLoad() {
        super.viewDidLoad()

        // 1. lock the rotation
        let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appdelegate.shouldRotate = false

        // 2. Force the device in landscape mode when the view controller gets loaded
        UIDevice.currentDevice().setValue(UIInterfaceOrientation.LandscapeRight.rawValue, forKey: "orientation")
    }

    override func shouldAutorotate() -> Bool {
        // 3. Lock autorotate
        return false
    }

    override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return [UIInterfaceOrientationMask.LandscapeRight, UIInterfaceOrientationMask.LandscapeLeft]
    }


    override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {

        // 4. Only allow Landscape
        return UIInterfaceOrientation.LandscapeRight
    }

    // 5. Restoring the locked-rotation before controller disappeared
    override func viewWillDisappear(animated: Bool) {
        let appdelegate = UIApplication.sharedApplication().delegate as! AppDelegate
        appdelegate.shouldRotate = true
    }
person Jorge Casariego    schedule 24.02.2016

** Добавьте в свой файл AppDelegate: *

var orientationLock = UIInterfaceOrientationMask.all
  func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return self.orientationLock
  }

  struct AppUtility {
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
      if let delegate = UIApplication.shared.delegate as? AppDelegate {
        delegate.orientationLock = orientation
      }
    }

    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
      self.lockOrientation(orientation)
      UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }
  }

Добавьте в viewcontroller, который вы хотите принудительно ориентировать:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    AppDelegate.AppUtility.lockOrientation(.portrait)
  }

  override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    AppDelegate.AppUtility.lockOrientation(.all)
  }
person Burak Ogutken    schedule 22.09.2017

Я нашел это по аналогичному вопросу. Ссылка

Прежде всего, я действительно благодарен zellb, который дал мне этот ответ и заставил меня понять. Чтобы установить ориентацию устройства для одного контроллера представления на портретную, а других на оба, вы можете установить это в AppDelegate.swift с помощью этой функции, которая имела supportedInterfaceOrientationsForWindow

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow) -> Int {

return checkOrientation(self.window?.rootViewController?)// This is the custom function that u need to set your custom view to each orientation which u want to lock

}

И вот функция, которая проверяет для каждого контроллера представления, чтобы установить портретную или полную ориентацию на основе того, что вы хотите.

func checkOrientation(viewController:UIViewController?)-> Int{

if(viewController == nil){

    return Int(UIInterfaceOrientationMask.All.rawValue)//All means all orientation

}else if (viewController is SignInViewController){

    return Int(UIInterfaceOrientationMask.Portrait.rawValue)//This is sign in view controller that i only want to set this to portrait mode only

}else{

    return checkOrientation(viewController!.presentedViewController?)
}
}

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

Надеюсь, это поможет.

person studev18    schedule 29.04.2015

Просто поместите это в viewDidAppear:

let value = UIInterfaceOrientation.Portrait.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
person Mika    schedule 29.04.2015
comment
и вы все еще оставили там код, который у вас был? не вернуть в shouldAutoRotate? - person Mika; 29.04.2015

Swift 3 ответ:

В контроллере представления вы хотите заблокировать ориентацию

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return .portrait
}

Адаптировано из как заблокировать портретную ориентацию только для основных просмотреть с помощью Swift

person fallaciousreasoning    schedule 19.07.2017