web-dev-qa-db-fra.com

Swift - Comment détecter les changements d'orientation

Je souhaite ajouter deux images à une seule image (c'est-à-dire pour une image paysage et pour une autre image au portrait), mais je ne sais pas comment détecter les changements d'orientation à l'aide de Swift langues.

J'ai essayé cette réponse mais cela ne prend qu'une image

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    if UIDevice.currentDevice().orientation.isLandscape.boolValue {
        print("Landscape")
    } else {
        print("Portrait")
    }
}

Je suis nouveau dans le développement iOS, tout conseil serait grandement apprécié!

65
Raghuram
let const = "Background" //image name
let const2 = "GreyBackground" // image name
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.image = UIImage(named: const)
        // Do any additional setup after loading the view.
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        if UIDevice.current.orientation.isLandscape {
            print("Landscape")
            imageView.image = UIImage(named: const2)
        } else {
            print("Portrait")
            imageView.image = UIImage(named: const)
        }
    }
79
Rutvik Kanbargi

Swift Code ci-dessus mis à jour:

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

Swift Utilisation de NotificationCenter

override func viewDidLoad() {
    super.viewDidLoad()        

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

deinit {
     NotificationCenter.default.removeObserver(self)
}

func rotated() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
    } else {
        print("Portrait")
    }
}
51
maslovsa

Swift 4 +: Je l'utilisais pour la conception de clavier logiciel, et pour une raison quelconque, la méthode UIDevice.current.orientation.isLandscape n'arrêtait pas de me dire que c'était Portrait, alors voici ce que j'ai utilisé à la place:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    if(size.width > self.view.frame.size.width){
        //Landscape
    }
    else{
        //Portrait
    }
}
8
asetniop

Si vous utilisez Swift version> = 3.0, vous devez appliquer certaines mises à jour de code, comme d'autres l'ont déjà dit. N'oubliez pas d'appeler super:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

   super.viewWillTransition(to: size, with: coordinator)

   // YOUR CODE OR FUNCTIONS CALL HERE

}

Si vous envisagez d'utiliser StackView pour vos images, sachez que vous pouvez effectuer les opérations suivantes:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {

   super.viewWillTransition(to: size, with: coordinator)

   if UIDevice.current.orientation.isLandscape {

      stackView.axis = .horizontal

   } else {

      stackView.axis = .vertical

   } // else

}

Si vous utilisez Interface Builder, n'oubliez pas de sélectionner la classe personnalisée pour cet objet UIStackView dans la section Inspecteur d'identité du panneau de droite. Ensuite, créez simplement (également via Interface Builder) la référence IBOutlet à l'instance UIStackView personnalisée:

@IBOutlet weak var stackView: MyStackView!

Prenez l’idée et adaptez-la à vos besoins. J'espère que cela peut vous aider!

5
josuevhn

Swift 4

J'ai eu quelques problèmes mineurs lors de la mise à jour de la vue ViewControllers à l'aide de UIDevice.current.orientation, tels que la mise à jour des contraintes des cellules de la vue table lors de la rotation ou de l'animation de sous-vues.

Au lieu des méthodes ci-dessus, je compare actuellement la taille de la transition à celle des contrôleurs de vue. Cela semble être la bonne voie à suivre car on a accès aux deux à ce stade du code:

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    print("Will Transition to size \(size) from super view size \(self.view.frame.size)")

    if (size.width > self.view.frame.size.width) {
        print("Landscape")
    } else {
        print("Portrait")
    }

    if (size.width != self.view.frame.size.width) {
        // Reload TableView to update cell's constraints.
    // Ensuring no dequeued cells have old constraints.
        DispatchQueue.main.async {
            self.tableView.reloadData()
        }
    }


}

Sortie sur un iPhone 6:

Will Transition to size (667.0, 375.0) from super view size (375.0, 667.0) 
Will Transition to size (375.0, 667.0) from super view size (667.0, 375.0)
5
RLoniello

Swift 4.2, RxSwift

Si nous devons recharger collectionView.

NotificationCenter.default.rx.notification(UIDevice.orientationDidChangeNotification)
    .observeOn(MainScheduler.instance)
    .map { _ in }            
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)

Swift 4, RxSwift

Si nous devons recharger collectionView.

NotificationCenter.default.rx.notification(NSNotification.Name.UIDeviceOrientationDidChange)
    .observeOn(MainScheduler.instance)
    .map { _ in }            
    .bind(to: collectionView.rx.reloadData)
    .disposed(by: bag)
5
maslovsa

Je pense que la bonne réponse est en réalité une combinaison des deux approches: viewWIllTransition(toSize:) et NotificationCenter's UIDeviceOrientationDidChange.

viewWillTransition(toSize:) vous notifie avant la transition.

NotificationCenterUIDeviceOrientationDidChange vous notifie après.

Tu dois être très prudent. Par exemple, dans UISplitViewController, lorsque le périphérique effectue une rotation dans certaines orientations, le tableau DetailViewController apparaît sur le UISplitViewController's viewcontrollers et est transféré dans le nom UINavigationController du maître. Si vous recherchez le contrôleur de vue de détail avant la fin de la rotation, il se peut qu'il n'existe pas et se bloque.

3
MH175

Toutes les contributions précédentes sont correctes, mais une petite remarque:

a) si l'orientation est définie dans la liste de sélection, uniquement un portrait ou un exemple, vous serez pas notifié via viewWillTransition

b) si nous avons de toute façon besoin de savoir si l'utilisateur a fait pivoter l'appareil (par exemple, un jeu ou similaire), nous ne pouvons utiliser que:

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

testé sur Xcode8, iOS11

3
ingconti

Pour obtenir l'orientation correcte sur démarrage de l'application, vous devez le vérifier dans viewDidLayoutSubviews(). Les autres méthodes décrites ici ne fonctionneront pas.

Voici un exemple comment faire:

var mFirstStart = true

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    if (mFirstStart) {
        mFirstStart = false
        detectOrientation()
    }
}

func detectOrientation() {
    if UIDevice.current.orientation.isLandscape {
        print("Landscape")
        // do your stuff here for landscape
    } else {
        print("Portrait")
        // do your stuff here for portrait
    }
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    detectOrientation()
}

Cela fonctionnera toujours, sur première application, et si vous tournez lorsque l'application est en cours d'exécution.

1
lenooh