icon color ios swift orientation-changes

ios - color - ¿Cómo detectar el cambio de orientación?



ionic header color (20)

Estoy usando Swift y quiero cargar un UIViewController cuando gire en horizontal, ¿alguien puede indicarme la dirección correcta?

No puedo encontrar nada en línea y un poco confundido por la documentación.


Aquí hay una manera fácil de detectar la orientación del dispositivo: ( Swift 3 )

override func willRotate(to toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) { handleViewRotaion(orientation: toInterfaceOrientation) } //MARK: - Rotation controls func handleViewRotaion(orientation:UIInterfaceOrientation) -> Void { switch orientation { case .portrait : print("portrait view") break case .portraitUpsideDown : print("portraitUpsideDown view") break case .landscapeLeft : print("landscapeLeft view") break case .landscapeRight : print("landscapeRight view") break case .unknown : break } }


Así es como lo hice funcionar:

En AppDelegate.swift dentro de la función didFinishLaunchingWithOptions puse:

NotificationCenter.default.addObserver(self, selector: #selector(AppDelegate.rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

y luego dentro de la clase AppDelegate pongo la siguiente función:

func rotated() { if UIDeviceOrientationIsLandscape(UIDevice.current.orientation) { print("Landscape") } if UIDeviceOrientationIsPortrait(UIDevice.current.orientation) { print("Portrait") } }

Espero que esto ayude a los demás!

¡Gracias!


Desde iOS 8, esta es la forma correcta de hacerlo.

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) coordinator.animate(alongsideTransition: { context in // This is called during the animation }, completion: { context in // This is called after the rotation is finished. Equal to deprecated `didRotate` }) }


El uso de la propiedad -orientation de UIDevice no es correcto (incluso si pudiera funcionar en la mayoría de los casos) y podría dar lugar a algunos errores, por ejemplo, UIDeviceOrientation también considera la orientación del dispositivo si está boca arriba o hacia abajo, no hay par directo en UIInterfaceOrientation enum para esos valores.
Además, si bloquea su aplicación en alguna orientación particular, UIDevice le dará la orientación del dispositivo sin tener eso en cuenta.
Por otro lado, iOS8 ha dejado de utilizar la propiedad interfaceOrientation en la clase UIViewController .
Hay 2 opciones disponibles para detectar la orientación de la interfaz:

  • Usa la orientación de la barra de estado
  • Use clases de tamaño, en iPhone si no se anulan, podrían darle una forma de entender la orientación actual de la interfaz

Lo que aún falta es una forma de entender la dirección de un cambio en la orientación de la interfaz, que es muy importante durante las animaciones.
En la sesión de WWDC 2014 "Ver avance del controlador en iOS8", el hablante también proporciona una solución a ese problema, utilizando el método que reemplaza -will/DidRotateToInterfaceOrientation .

Aquí la solución propuesta se implementó parcialmente, más información here :

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { let orientation = orientationFromTransform(coordinator.targetTransform()) let oldOrientation = UIApplication.sharedApplication().statusBarOrientation myWillRotateToInterfaceOrientation(orientation,duration: duration) coordinator.animateAlongsideTransition({ (ctx) in self.myWillAnimateRotationToInterfaceOrientation(orientation, duration:duration) }) { (ctx) in self.myDidAnimateFromInterfaceOrientation(oldOrientation) } }


En el objetivo C

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator

En veloz

func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

Anule este método para detectar el cambio de orientación.


Fácil, esto funciona en iOS8 y 9 / Swift 2 / Xcode7, simplemente coloca este código dentro de tu viewcontroller.swift. Imprimirá las dimensiones de la pantalla con cada cambio de orientación, en su lugar puede poner su propio código:

override func didRotateFromInterfaceOrientation(fromInterfaceOrientation: UIInterfaceOrientation) { getScreenSize() } var screenWidth:CGFloat=0 var screenHeight:CGFloat=0 func getScreenSize(){ screenWidth=UIScreen.mainScreen().bounds.width screenHeight=UIScreen.mainScreen().bounds.height print("SCREEN RESOLUTION: "+screenWidth.description+" x "+screenHeight.description) }


Me gusta verificar la notificación de orientación porque puede agregar esta característica en cualquier clase, no necesita ser una vista o un controlador de vista. Incluso en tu aplicación delegada.

//ask the system to start notifying when interface change UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications() //add the observer NSNotificationCenter.defaultCenter().addObserver( self, selector: #selector(self.orientationChanged(_:)), name: UIDeviceOrientationDidChangeNotification, object: nil)

que almacenar en caché la notificación

func orientationChanged(notification : NSNotification) { //your code there }


Mi enfoque es similar a lo que muestra bpedit arriba, pero con un enfoque iOS 9+. Quería cambiar el alcance de FSCalendar cuando la vista gira.

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition({ (context) in if size.height < size.width { self.calendar.setScope(.Week, animated: true) self.calendar.appearance.cellShape = .Rectangle } else { self.calendar.appearance.cellShape = .Circle self.calendar.setScope(.Month, animated: true) } }, completion: nil) }

Esto a continuación funcionó, pero me sentí tímido al respecto :)

coordinator.animateAlongsideTransition({ (context) in if size.height < size.width { self.calendar.scope = .Week self.calendar.appearance.cellShape = .Rectangle } }) { (context) in if size.height > size.width { self.calendar.scope = .Month self.calendar.appearance.cellShape = .Circle } }


Necesito detectar la rotación mientras uso la cámara con AVFoundation , y descubrí que los didRotate ( ahora obsoleto ) y willTransition no eran confiables para mis necesidades. Usar la notificación publicada por David sí funcionó, pero no es actual para Swift 3.x / 4.x.

Swift 4.0 Con Swift 4.0, Apple nos ha alentado a evitar el uso de #selector , por lo que este enfoque utiliza un bloque de finalización ahora. Este enfoque también es compatible con Swift 3.x y sería el enfoque recomendado en el futuro.

Esta es la advertencia del compilador que recibirá en un proyecto de Swift 4.x si usa la función #selector :

Entrada en rápida evolución sobre este cambio .

Configurar la devolución de llamada:

// If you do not use the notification var in your callback, // you can safely replace it with _ var didRotate: (Notification) -> Void = { notification in switch UIDevice.current.orientation { case .landscapeLeft, .landscapeRight: print("landscape") case .portrait, .portraitUpsideDown: print("Portrait") default: print("other") } }

Configura la notificación:

NotificationCenter.default.addObserver(forName: .UIDeviceOrientationDidChange, object: nil, queue: .main, using: didRotate)

Romper en pedazos:

NotificationCenter.default.removeObserver(self, name: .UIDeviceOrientationDidChange, object: nil)

Swift 3.0 Esta fue mi solución anterior, pero recomendaría usar la solución 4.0 anterior:

Configura la notificación:

NotificationCenter.default.addObserver(self, selector: #selector(rotated), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)

Responda a la notificación:

func rotated() { switch UIDevice.current.orientation { case .landscapeLeft, .landscapeRight: print("landscape") default: print("Portrait") } }

Destruye la notificación:

NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil)


Sé que esta pregunta es para Swift , pero ya que es uno de los principales enlaces para una búsqueda en Google y si buscas el mismo código en Objective-C :

// add the observer [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rotated:) name:UIDeviceOrientationDidChangeNotification object:nil]; // remove the observer [[NSNotificationCenter defaultCenter] removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil]; // method signature - (void)rotated:(NSNotification *)notification { // do stuff here }


Si desea hacer algo DESPUÉS de completar la rotación, puede usar el UIViewControllerTransitionCoordinator finalización UIViewControllerTransitionCoordinator como este

public override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransition(to: size, with: coordinator) // Hook in to the rotation animation completion handler coordinator.animate(alongsideTransition: nil) { (_) in // Updates to your UI... self.tableView.reloadData() } }



Uso UIUserInterfaceSizeClass para detectar una orientación modificada en una clase UIViewController así:

override func willTransition(to newCollection: UITraitCollection, with coordinator: UIViewControllerTransitionCoordinator) { let isiPadLandscapePortrait = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .regular let isiPhonePlustLandscape = newCollection.horizontalSizeClass == .regular && newCollection.verticalSizeClass == .compact let isiPhonePortrait = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .regular let isiPhoneLandscape = newCollection.horizontalSizeClass == .compact && newCollection.verticalSizeClass == .compact if isiPhonePortrait { // do something... } }


Verifique si la rotación ha cambiado con: viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator)

Con coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) puede verificar si la transición ha finalizado.

Vea el código a continuación:

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition(nil) { (UIViewControllerTransitionCoordinatorContext) in // if you want to execute code after transition finished print("Transition finished") } if size.height < size.width { // Landscape print("Landscape") } else { // Portrait print("Portrait") } }


Implementación completa de trabajo de cómo detectar cambios de orientación en Swift 3.0.

Elegí usar esta implementación porque las orientaciones del teléfono face up y face down eran importantes para mí, y quería que la vista cambiara solo cuando supiera que la orientación estaba en la posición especificada.

import UIKit class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() //1 NotificationCenter.default.addObserver(self, selector: #selector(deviceOrientationDidChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) } deinit { //3 NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) } func deviceOrientationDidChange() { //2 switch UIDevice.current.orientation { case .faceDown: print("Face down") case .faceUp: print("Face up") case .unknown: print("Unknown") case .landscapeLeft: print("Landscape left") case .landscapeRight: print("Landscape right") case .portrait: print("Portrait") case .portraitUpsideDown: print("Portrait upside down") } } }

Las piezas importantes a tener en cuenta son:

  1. Escucha la transmisión de notificación DeviceOrientationDidChange y la vincula a la función deviceOrientationDidChange
  2. Luego, enciende la orientación del dispositivo, asegúrese de tener en cuenta que a veces hay una orientación unknown .
  3. Como cualquier notificación, antes de que viewController esté desinicializado, asegúrese de dejar de observar el flujo de notificaciones.

Espero que alguien encuentre esto útil.


Para Swift 3

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { if UIDevice.current.orientation.isLandscape { //Landscape } else { //Portrait } }


Swift 3 | Notificación de UIDeviceOrientationDidChange observada con demasiada frecuencia

El siguiente código imprime "deviceDidRotate" cada vez que su dispositivo cambia de orientación en el espacio 3D, independientemente de un cambio de orientación vertical a horizontal. Por ejemplo, si mantiene el teléfono en orientación vertical e inclínelo hacia adelante y hacia atrás, se llama repetidamente deviceDidRotate ().

override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(deviceDidRotate), name: .UIDeviceOrientationDidChange, object: nil ) } func deviceDidRotate() { print("deviceDidRotate") }

Para solucionar este problema, puede mantener la orientación del dispositivo anterior y comprobar si hay algún cambio en deviceDidRotate ().

var previousDeviceOrientation: UIDeviceOrientation = UIDevice.current.orientation override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(deviceDidRotate), name: .UIDeviceOrientationDidChange, object: nil ) } func deviceDidRotate() { if UIDevice.current.orientation == previousDeviceOrientation { return } previousDeviceOrientation = UIDevice.current.orientation print("deviceDidRotate") }

O puede usar una notificación diferente que solo recibe una llamada cuando el dispositivo cambia de horizontal a vertical. En este caso, querrá utilizar la notificación UIApplicationDidChangeStatusBarOrientation .

override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver( self, selector: #selector(deviceDidRotate), name: .UIApplicationDidChangeStatusBarOrientation, object: nil ) } func deviceDidRotate() { print("deviceDidRotate") }


- (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(OrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil]; } -(void)OrientationDidChange:(NSNotification*)notification { UIDeviceOrientation Orientation=[[UIDevice currentDevice]orientation]; if(Orientation==UIDeviceOrientationLandscapeLeft || Orientation==UIDeviceOrientationLandscapeRight) { NSLog(@"Landscape"); } else if(Orientation==UIDeviceOrientationPortrait) { NSLog(@"Potrait Mode"); } }

NOTA: Solo use este código para identificar a UIViewController en qué orientación


override func didRotate(from fromInterfaceOrientation: UIInterfaceOrientation) { //swift 3 getScreenSize() } func getScreenSize(){ let screenWidth = UIScreen.main.bounds.width let screenHeight = UIScreen.main.bounds.height print("SCREEN RESOLUTION: /(screenWidth.description) x /(screenHeight.description)") }


override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) { if UIDevice.current.orientation.isLandscape { print("Landscape") } else { print("Portrait") } }