Avant iOS 8, nous utilisions le code ci-dessous conjointement aux méthodes supportedInterfaceOrientations et shouldAutoRotate pour imposer l'orientation de l'application à une orientation particulière. J'ai utilisé l'extrait de code ci-dessous pour faire pivoter l'application par programme selon l'orientation souhaitée. Tout d'abord, je change l'orientation de la barre d'état. Ensuite, il suffit de présenter et de supprimer immédiatement une vue modale pour faire pivoter la vue selon l'orientation souhaitée.
[[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationLandscapeRight animated:YES];
UIViewController *c = [[UIViewController alloc]init];
[self presentViewController:vc animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
Mais cela échoue dans iOS 8. En outre, j’ai vu quelques réponses concernant le débordement de pile où des personnes ont suggéré de toujours éviter cette approche à partir d’iOS 8.
Pour être plus précis, mon application est un type d'application universel. Il y a trois contrôleurs au total.
Contrôleur First View - Il devrait prendre en charge toutes les orientations dans iPad et uniquement en mode portrait (bouton d'accueil enfoncé) dans iPhone.
Contrôleur Second View - Il ne devrait supporter que le droit de paysage dans toutes les conditions
Third View controller - Il ne devrait supporter que le droit de paysage dans toutes les conditions
Nous utilisons le contrôleur de navigation pour la navigation de page. À partir du premier contrôleur de vue, lors d’une action sur un clic de bouton, nous poussons le second sur la pile. Ainsi, lorsque le second contrôleur de vue arrive, quelle que soit l'orientation du périphérique, l'application ne doit être verrouillée qu'en mode paysage.
Ci-dessous, mes méthodes shouldAutorotate
et supportedInterfaceOrientations
dans les deuxième et troisième contrôleurs de vue.
-(NSUInteger)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskLandscapeRight;
}
-(BOOL)shouldAutorotate {
return NO;
}
Existe-t-il une solution à ce problème ou un meilleur moyen de verrouiller un contrôleur de vue avec une orientation particulière pour iOS 8. Aidez-nous!
Pour iOS 7 - 10:
Objectif c:
[[UIDevice currentDevice] setValue:@(UIInterfaceOrientationLandscapeLeft) forKey:@"orientation"];
[UINavigationController attemptRotationToDeviceOrientation];
Swift 3:
let value = UIInterfaceOrientation.landscapeLeft.rawValue
UIDevice.current.setValue(value, forKey: "orientation")
UINavigationController.attemptRotationToDeviceOrientation()
Appelez-le simplement dans - viewDidAppear:
du contrôleur de vue présenté.
La rotation d'orientation est un peu plus compliquée si vous êtes à l'intérieur de UINavigationController
ou UITabBarController
. Le problème est que si un contrôleur de vue est intégré à l'un de ces contrôleurs, le contrôleur de navigation ou de barre de tabulation est prioritaire et prend les décisions relatives à l'autorotation et aux orientations prises en charge.
J'utilise les 2 extensions suivantes sur UINavigationController et UITabBarController afin que les contrôleurs de vue intégrés à l'un de ces contrôleurs puissent prendre les décisions.
Swift 2.3
extension UINavigationController {
public override func supportedInterfaceOrientations() -> Int {
return visibleViewController.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
}
extension UITabBarController {
public override func supportedInterfaceOrientations() -> Int {
if let selected = selectedViewController {
return selected.supportedInterfaceOrientations()
}
return super.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
if let selected = selectedViewController {
return selected.shouldAutorotate()
}
return super.shouldAutorotate()
}
}
Swift 3
extension UINavigationController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return visibleViewController?.supportedInterfaceOrientations ?? super.supportedInterfaceOrientations
}
open override var shouldAutorotate: Bool {
return visibleViewController?.shouldAutorotate ?? super.shouldAutorotate
}
}
extension UITabBarController {
open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let selected = selectedViewController {
return selected.supportedInterfaceOrientations
}
return super.supportedInterfaceOrientations
}
open override var shouldAutorotate: Bool {
if let selected = selectedViewController {
return selected.shouldAutorotate
}
return super.shouldAutorotate
}
}
Vous pouvez maintenant remplacer la méthode supportedInterfaceOrientations
ou shouldAutoRotate
dans le contrôleur de vue que vous souhaitez verrouiller, sinon vous pouvez omettre les remplacements dans les autres contrôleurs de vue dont vous souhaitez hériter le comportement d'orientation par défaut spécifié dans le plist de votre application
class ViewController: UIViewController {
override func shouldAutorotate() -> Bool {
return false
}
}
class ViewController: UIViewController {
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
}
En théorie, cela devrait fonctionner pour toutes les hiérarchies de contrôleurs de vues complexes, mais j'ai remarqué un problème avec UITabBarController. Pour une raison quelconque, il souhaite utiliser une valeur d'orientation par défaut. Consultez le blog suivant si vous souhaitez en savoir plus sur la résolution de certains problèmes:
C'est ce qui a fonctionné pour moi:
Appelez-le dans votre méthode viewDidAppear :.
- (void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[UIViewController attemptRotationToDeviceOrientation];
}
J'ai trouvé que s'il s'agit d'un contrôleur de vue présenté, vous pouvez remplacer preferredInterfaceOrientationForPresentation
Rapide:
override func supportedInterfaceOrientations() -> Int {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return UIInterfaceOrientation.LandscapeLeft
}
override func shouldAutorotate() -> Bool {
return false
}
Cela me permet de travailler dans Swift 2 iOS 8.x:
PS (cette méthode n’a pas besoin de surcharger les fonctions d’orientation telles que shouldautorotate sur chaque viewController, une seule méthode sur AppDelegate)
Cochez la case "nécessite un plein écran" dans les informations générales de votre projet.
Donc, sur AppDelegate.Swift, créez une variable:
var enableAllOrientation = false
Alors, mettez aussi cette fonction:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if (enableAllOrientation == true){
return UIInterfaceOrientationMask.All
}
return UIInterfaceOrientationMask.Portrait
}
Ainsi, dans chaque classe de votre projet, vous pouvez définir cette variable dans viewWillAppear:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.enableAllOrientation = true
}
Si vous devez faire des choix en fonction du type d'appareil, vous pouvez le faire:
override func viewWillAppear(animated: Bool)
{
super.viewWillAppear(animated)
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
switch UIDevice.currentDevice().userInterfaceIdiom {
case .Phone:
// It's an iPhone
print(" - Only portrait mode to iPhone")
appDelegate.enableAllOrientation = false
case .Pad:
// It's an iPad
print(" - All orientation mode enabled on iPad")
appDelegate.enableAllOrientation = true
case .Unspecified:
// Uh, oh! What could it be?
appDelegate.enableAllOrientation = false
}
}
Tout d’abord, c’est une mauvaise idée. En général, il y a quelque chose qui ne va pas avec l’architecture de votre application, mais, sh..t happens
, si tel est le cas, vous pouvez essayer de faire quelque chose comme ci-dessous:
final class OrientationController {
static private (set) var allowedOrientation:UIInterfaceOrientationMask = [.all]
// MARK: - Public
class func lockOrientation(_ orientationIdiom: UIInterfaceOrientationMask) {
OrientationController.allowedOrientation = [orientationIdiom]
}
class func forceLockOrientation(_ orientation: UIInterfaceOrientation) {
var mask:UIInterfaceOrientationMask = []
switch orientation {
case .unknown:
mask = [.all]
case .portrait:
mask = [.portrait]
case .portraitUpsideDown:
mask = [.portraitUpsideDown]
case .landscapeLeft:
mask = [.landscapeLeft]
case .landscapeRight:
mask = [.landscapeRight]
}
OrientationController.lockOrientation(mask)
UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
}
}
Ensuite, dans AppDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// do stuff
OrientationController.lockOrientation(.portrait)
return true
}
// MARK: - Orientation
func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
return OrientationController.allowedOrientation
}
Et chaque fois que vous souhaitez changer d'orientation, procédez comme suit:
OrientationController.forceLockOrientation(.landscapeRight)
Remarque: Parfois, le périphérique peut ne pas être mis à jour à partir de cet appel. Vous devrez peut-être procéder comme suit.
OrientationController.forceLockOrientation(.portrait)
OrientationController.forceLockOrientation(.landscapeRight)
C'est tout
Cela devrait fonctionner à partir d'iOS 6, mais je ne l'ai testé que sur iOS 8. Sous-classe UINavigationController
et remplacer les méthodes suivantes:
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)shouldAutorotate {
return NO;
}
Ou demandez au contrôleur de vue visible
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
return self.visibleViewController.preferredInterfaceOrientationForPresentation;
}
- (BOOL)shouldAutorotate {
return self.visibleViewController.shouldAutorotate;
}
et mettre en œuvre les méthodes là-bas.
Ceci est un retour aux commentaires dans réponse de Sid Shah , concernant la désactivation des animations à l'aide de:
[UIView setAnimationsEnabled:enabled];
Code:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:NO];
[UIView setAnimationsEnabled:NO];
// Stackoverflow #26357162 to force orientation
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:NO];
[UIView setAnimationsEnabled:YES];
}
Sur Xcode 8
, les méthodes sont converties en propriétés. Par conséquent, les méthodes suivantes fonctionnent avec Swift
:
override public var supportedInterfaceOrientations: UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.portrait
}
override public var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
return UIInterfaceOrientation.portrait
}
override public var shouldAutorotate: Bool {
return true
}
Si vous utilisez navigationViewController, vous devez créer votre propre super-classe pour cela et remplacer:
- (BOOL)shouldAutorotate {
id currentViewController = self.topViewController;
if ([currentViewController isKindOfClass:[SecondViewController class]])
return NO;
return YES;
}
cela désactivera la rotation dans SecondViewController mais si vous poussez votre SecondViewController lorsque Si l'appareil est en orientation portrait, votre SecondViewController apparaîtra en mode portrait.
Supposons que vous utilisez le storyboard. Vous devez créer un segue manuel ( Comment ) et dans votre méthode "onClick":
- (IBAction)onPlayButtonClicked:(UIBarButtonItem *)sender {
NSNumber *value = [NSNumber numberWithInt:UIInterfaceOrientationLandscapeLeft];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
[self performSegueWithIdentifier:@"PushPlayerViewController" sender:self];
}
Cela forcera l'orientation paysage avant que votre superclasse ne désactive la fonctionnalité d'autorotation.
J'ai essayé de nombreuses solutions, mais celle qui a fonctionné est la suivante:
Il n'est pas nécessaire de modifier le info.plist
dans ios 8 et 9.
- (BOOL) shouldAutorotate {
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return (UIInterfaceOrientationPortrait | UIInterfaceOrientationPortraitUpsideDown);
}
Orientations possibles à partir de la Apple Documentation :
UIInterfaceOrientationUnknown
L'orientation de l'appareil ne peut pas être déterminée.
UIInterfaceOrientationPortrait
L’appareil est en mode portrait, l’appareil étant maintenu à la verticale et le bouton principal situé en bas.
UIInterfaceOrientationPortraitUpsideDown
L'appareil est en mode portrait mais à l'envers, avec l'appareil maintenu en position verticale et le bouton principal situé en haut.
UIInterfaceOrientationLandscapeLeft
L’appareil est en mode paysage, l’appareil étant maintenu droit et le bouton principal situé à gauche.
UIInterfaceOrientationLandscapeRight
L’appareil est en mode paysage, l’appareil maintenu en position verticale et le bouton principal situé à droite.
La combinaison des réponses Sids et Koreys a fonctionné pour moi.
Extension du contrôleur de navigation:
extension UINavigationController {
public override func shouldAutorotate() -> Bool {
return visibleViewController.shouldAutorotate()
}
}
Puis désactivation de la rotation sur la vue unique
class ViewController: UIViewController {
override func shouldAutorotate() -> Bool {
return false
}
}
Et en tournant à l'orientation appropriée avant la segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "SomeSegue")
{
let value = UIInterfaceOrientation.Portrait.rawValue;
UIDevice.currentDevice().setValue(value, forKey: "orientation")
}
}
[iOS9 +] Si quelqu'un traînait jusqu'au bout car aucune des solutions ci-dessus ne fonctionnait, et si vous présentiez la vue que vous souhaitez changer d'orientation par séquence, vous voudrez peut-être vérifier ceci.
Vérifiez le type de présentation de votre segue. Le mien était "sur le contexte actuel". Lorsque je l'ai changé en plein écran, cela a fonctionné.
Grâce à @GabLeRoux, j'ai trouvé cette solution.
Mes exigences sont
AVPlayerViewController
pour lire la vidéoLors de la lecture d'une vidéo, s'il s'agit d'un paysage, laissez l'écran pivoter à droite et à gauche. S'il s'agit d'un portrait, verrouillez la vue en mode portrait uniquement.
Tout d’abord, définissez supportedInterfaceOrientationsForWindow
dans AppDelegate.Swift
var portrait = true
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if portrait {
return .Portrait
} else {
return .Landscape
}
}
Deuxièmement, dans votre contrôleur de vue principale, définissez les fonctions suivantes
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
print("\(#function)")
return .Portrait
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return .Portrait
}
override func shouldAutorotate() -> Bool {
return false
}
Ensuite, vous devez sous-classe AVPlayerViewController
class MyPlayerViewController: AVPlayerViewController {
var size: CGSize?
var supportedOrientationMask: UIInterfaceOrientationMask?
var preferredOrientation: UIInterfaceOrientation?
override func viewDidLoad() {
super.viewDidLoad()
if let size = size {
if size.width > size.height {
self.supportedOrientationMask =[.LandscapeLeft,.LandscapeRight]
self.preferredOrientation =.LandscapeRight
} else {
self.supportedOrientationMask =.Portrait
self.preferredOrientation =.Portrait
}
}
}
Remplacer ces trois fonctions dans MyPlayerViewController.Swift
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return self.supportedOrientationMask!
}
override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {
return self.preferredOrientation!
}
Parce que l'utilisateur peut faire pivoter paysage de l'appareil à gauche ou à droite, nous devons définir la rotation automatique sur true
override func shouldAutorotate() -> Bool {
return true
}
Enfin, créez une instance MyPlayerViewController
dans votre contrôleur de vue et définissez la valeur de la taille de la propriété.
let playerViewController = MyPlayerViewController()
// Get the thumbnail
let thumbnail = MyAlbumFileManager.sharedManager().getThumbnailFromMyVideoMedia(......)
let size = thumbnail?.size
playerViewController.size = size
Initiez votre lecteur avec la variable videoUrl
appropriée, puis affectez-le à playerViewController
. Bon codage!
La solution supérieure ci-dessus:
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
cela ne fonctionnait pas pour moi lorsque je l'ai appelé dans viewDidAppear du contrôleur de vue présenté. Cependant, cela a fonctionné lorsque je l'ai appelé dans preparForSegue dans le contrôleur de vue de présentation.
(Désolé, pas assez de points de réputation pour commenter cette solution, je devais donc l'ajouter comme ça)
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[UIViewController attemptRotationToDeviceOrientation];
}
Selon réponse de Korey Hinton
Swift 2.2:
extension UINavigationController {
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return visibleViewController!.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
return visibleViewController!.shouldAutorotate()
}
}
extension UITabBarController {
public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
if let selected = selectedViewController {
return selected.supportedInterfaceOrientations()
}
return super.supportedInterfaceOrientations()
}
public override func shouldAutorotate() -> Bool {
if let selected = selectedViewController {
return selected.shouldAutorotate()
}
return super.shouldAutorotate()
}
}
Désactiver la rotation
override func shouldAutorotate() -> Bool {
return false
}
Verrouillage sur une orientation spécifique
override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
return UIInterfaceOrientationMask.Portrait
}
J'ai essayé quelques solutions ici et la chose importante à comprendre est que c'est le contrôleur de vue racine qui déterminera s'il tournera ou non.
J'ai créé le projet objective-c suivant github.com/GabLeRoux/RotationLockInTabbedViewChild avec un exemple de travail de TabbedViewController
où une vue enfant est est autorisée à pivoter et l’autre vue enfant est verrouillée en portrait.
Ce n'est pas parfait, mais cela fonctionne et la même idée devrait fonctionner pour d'autres types de vues telles que NavigationViewController
. :)
Il semble encore y avoir un débat sur la meilleure façon d'accomplir cette tâche, alors j'ai pensé partager mon approche (de travail). Ajoutez le code suivant dans votre implémentation UIViewController
:
- (void) viewWillAppear:(BOOL)animated
{
[UIViewController attemptRotationToDeviceOrientation];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return (toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft);
}
-(BOOL)shouldAutorotate
{
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskLandscapeLeft;
}
Pour cet exemple, vous devrez également définir les orientations de périphérique autorisées sur "Paysage gauche" dans les paramètres de votre projet (ou directement dans info.plist
). Changez simplement l’orientation spécifique que vous voulez forcer si vous voulez autre chose que LandscapeLeft.
La clé pour moi était l'appel attemptRotationToDeviceOrientation
dans viewWillAppear
- sans quoi la vue ne pourrait pas pivoter correctement sans une rotation physique de l'appareil.
J'ai le même problème et je perds beaucoup de temps à le résoudre. Alors maintenant, j'ai ma solution. Mon paramètre d'application est uniquement compatible avec Portrait seulement. Cependant, certains écrans de mon application n'ont besoin que de paysage. Je le répare en ayant une variable isShouldRotate à . Et la fonction sur AppDelegate :
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
if isShouldRotate == true {
return Int(UIInterfaceOrientationMask.Landscape.rawValue)
}
return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}
Et enfin, lorsqu'un ViewControllerA a besoin d'un état paysage. Faites juste cela: avant Push/present à ViewControllerA attribue isShouldRotate à true . N'oubliez pas que lorsque le menu contextuel est affiché/supprimé, le contrôleur affecte isShouldRotate à false à viewWillDisappear .
Selon la solution montrée par @ sid-sha, vous devez tout mettre dans la méthode viewDidAppear:
, sinon vous ne obtiendrez pas le didRotateFromInterfaceOrientation:
renvoyé, donc quelque chose comme:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
if (interfaceOrientation == UIInterfaceOrientationLandscapeLeft ||
interfaceOrientation == UIInterfaceOrientationLandscapeRight) {
NSNumber *value = [NSNumber numberWithInt:interfaceOrientation];
[[UIDevice currentDevice] setValue:value forKey:@"orientation"];
}
}
On dirait que même toi, ici, a tellement de réponses que personne ne me suffisait. Je voulais forcer l’orientation, puis je revenais à l’orientation des appareils, mais [UIViewController attemptRotationToDeviceOrientation];
ne fonctionnait tout simplement pas. Ce qui a également compliqué les choses, c’est que j’ai ajouté shouldAutorotate à false sur la base d’une réponse et que je ne pouvais pas faire en sorte que les effets souhaités soient correctement reconvertis dans tous les scénarios.
Alors voici ce que j'ai fait:
Avant de pousser le contrôleur en appel dans son constructeur init, ceci:
_userOrientation = UIDevice.currentDevice.orientation;
[UIDevice.currentDevice setValue:@(UIInterfaceOrientationPortrait) forKey:@"orientation"];
[self addNotificationCenterObserver:@selector(rotated:)
name:UIDeviceOrientationDidChangeNotification];
Je sauvegarde donc la dernière orientation de l'appareil et m'inscris pour l'événement de changement d'orientation. L'événement de changement d'orientation est simple:
- (void)rotated:(NSNotification*)notification {
_userOrientation = UIDevice.currentDevice.orientation;
}
Et à ma vue, je me contente de revenir à l’orientation que j’ai en tant qu’utilisateurOreintation:
- (void)onViewDismissing {
super.onViewDismissing;
[UIDevice.currentDevice setValue:@(_userOrientation) forKey:@"orientation"];
[UIViewController attemptRotationToDeviceOrientation];
}
Et cela doit être là aussi:
- (BOOL)shouldAutorotate {
return true;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
Et aussi contrôleur de navigation doit déléguer à devraitAutorotate et supportéInterfaceOrientations, mais que la plupart des gens ont déjà je crois.
PS: Désolé, j'utilise des extensions et des classes de base, mais les noms sont assez significatifs, donc le concept est compréhensible, il créera encore plus d’extensions car il n’est plus très joli à l’heure actuelle.
Dans AppDelegate
:
func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
if let topController = UIViewController.topMostViewController() {
if topController is XXViewController {
return [.Portrait, .LandscapeLeft]
}
}
return [.Portrait]
}
XXViewController
est le ViewController que vous souhaitez prendre en charge en mode Paysage.
Alors la solution Sunny Shah fonctionnerait dans votre XXViewController
sur n'importe quelle version iOS:
let value = UIInterfaceOrientation.LandscapeLeft.rawValue
UIDevice.currentDevice().setValue(value, forKey: "orientation")
C’est la fonction utilitaire permettant de trouver le plus élevé des ViewController.
extension UIViewController {
/// Returns the current application's top most view controller.
public class func topMostViewController() -> UIViewController? {
let rootViewController = UIApplication.sharedApplication().windows.first?.rootViewController
return self.topMostViewControllerOfViewController(rootViewController)
}
/// Returns the top most view controller from given view controller's stack.
class func topMostViewControllerOfViewController(viewController: UIViewController?) -> UIViewController? {
// UITabBarController
if let tabBarController = viewController as? UITabBarController,
let selectedViewController = tabBarController.selectedViewController {
return self.topMostViewControllerOfViewController(selectedViewController)
}
// UINavigationController
if let navigationController = viewController as? UINavigationController,
let visibleViewController = navigationController.visibleViewController {
return self.topMostViewControllerOfViewController(visibleViewController)
}
// presented view controller
if let presentedViewController = viewController?.presentedViewController {
return self.topMostViewControllerOfViewController(presentedViewController)
}
// child view controller
for subview in viewController?.view?.subviews ?? [] {
if let childViewController = subview.nextResponder() as? UIViewController {
return self.topMostViewControllerOfViewController(childViewController)
}
}
return viewController
}
}
Pour moi, le niveau supérieur VC devait mettre en œuvre les substitutions d'orientation. L'utilisation de VC dans la pile n'aura aucun effet si le VC supérieur n'est pas implémenté.
VC-main
|
-> VC 2
|
-> VC 3
Seul VC-Main est écouté, essentiellement lors de mes tests.
Utilisez-le pour verrouiller l’orientation du contrôleur de vue, testé sur IOS 9:
// Verrouille l'orientation en paysage à droite
-(UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight;
}
-(NSUInteger)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController {
return UIInterfaceOrientationMaskLandscapeRight;
}