28 votes

Autorotate dans iOS 6 a un comportement étrange

J'ai une application UITabBarController qui lit des vidéos et affiche d'autres informations dans d'autres onglets de UITabBar. Dans iOS 6, les méthodes de rotation de UIView ont été dépréciées, et maintenant je dois utiliser les méthodes shouldAutoRotate et supportedInterfaceOrientations. Pour la lecture vidéo, j'utilise MPMoviePlayerViewController.

Comment faire pivoter seulement cette vue de lecteur? Je peux seulement pivoter toute l'application, mais je ne veux pas le faire. Je présente MPMoviePlayerViewController mais il ne se pivot comme dans iOS 5 et antérieur.

Dans les réglages du fichier plist, j'ai défini une seule orientation d'interface en mode portrait. Si j'en définis une autre - toute l'application sera pivotée.

45voto

rocky Points 1847

À partir des notes de version du SDK iOS 6 d'Apple :

La rotation automatique change dans iOS 6. Dans iOS 6, la méthode shouldAutorotateToInterfaceOrientation: de UIViewController est obsolète. À sa place, vous devez utiliser les méthodes supportedInterfaceOrientationsForWindow: et shouldAutorotate.

Plus de responsabilités sont transférées à l'application et au délégué de l'application. Maintenant, les conteneurs iOS (comme UINavigationController) ne consultent pas leurs enfants pour déterminer s'ils doivent effectuer une rotation automatique. Par défaut, les orientations d'interface prises en charge d'une application et d'un contrôleur de vue sont définies sur UIInterfaceOrientationMaskAll pour l'idiome iPad et sur UIInterfaceOrientationMaskAllButUpsideDown pour l'idiome iPhone.

Les orientations d'interface prises en charge d'un contrôleur de vue peuvent changer au fil du temps, même celles prises en charge par une application. Le système demande au contrôleur de vue plein écran le plus haut (généralement le contrôleur de vue racine) ses orientations d'interface prises en charge chaque fois que l'appareil est en rotation ou chaque fois qu'un contrôleur de vue est présenté avec le style de présentation modale plein écran. De plus, les orientations prises en charge ne sont récupérées que si ce contrôleur de vue renvoie YES depuis sa méthode shouldAutorotate. Le système intersecte les orientations prises en charge du contrôleur de vue avec celles de l'application (telles que déterminées par le fichier Info.plist ou par la méthode application:supportedInterfaceOrientationsForWindow: du délégué de l'application) pour déterminer s'il faut effectuer une rotation.

Le système détermine si une orientation est prise en charge en intersectant la valeur renvoyée par la méthode supportedInterfaceOrientationsForWindow: de l'application avec la valeur renvoyée par la méthode supportedInterfaceOrientations du contrôleur de vue plein écran le plus haut. La méthode setStatusBarOrientation:animated: n'est pas obsolète. Elle fonctionne désormais uniquement si la méthode supportedInterfaceOrientations du contrôleur de vue plein écran le plus haut renvoie 0. Cela rend l'appelant responsable de garantir que l'orientation de la barre d'état est cohérente.

Pour des raisons de compatibilité, les contrôleurs de vue qui implémentent toujours la méthode shouldAutorotateToInterfaceOrientation: ne bénéficient pas des nouveaux comportements de rotation automatique. (En d'autres termes, ils ne passent pas à l'application, au délégué de l'application ou au fichier Info.plist pour déterminer les orientations prises en charge.) Au lieu de cela, la méthode shouldAutorotateToInterfaceOrientation: est utilisée pour synthétiser les informations qui seraient retournées par la méthode supportedInterfaceOrientations.

Si vous souhaitez que votre application entière tourne, vous devriez définir votre fichier Info.plist pour prendre en charge toutes les orientations. Maintenant, si vous voulez qu'une vue spécifique soit uniquement en mode portrait, vous devrez créer une sorte de sous-classe et remplacer les méthodes de rotation automatique pour ne retourner que le mode portrait. J'ai un exemple ici :

https://stackoverflow.com/a/12522119/1575017

13voto

Agat Points 1607

Wow! Une demi-journée passée et le problème résolu! Hi hi.

Comme le dit la documentation ci-dessus, c'est vraiment ça! Les points clés sont les suivants:

Plus de responsabilité est transférée vers l'application et le délégué de l'application. Maintenant, les conteneurs iOS (comme UINavigationController) ne consultent pas leurs enfants pour déterminer s'ils doivent pivoter automatiquement. Par défaut, une application et les orientations d'interface prises en charge d'un contrôleur de vue sont définies sur UIInterfaceOrientationMaskAll pour l'idiome iPad et UIInterfaceOrientationMaskAllButUpsideDown pour l'idiome iPhone.

Ainsi, chaque fois qu'il y a un changement avec le contrôleur racine, le système demande au délégué de l'application "Alors, on pivote ou pas?"

Si "on pivote":

les orientations prises en charge sont récupérées uniquement si ce contrôleur de vue renvoie YES de sa méthode shouldAutorotate.

ensuite, le système demande à notre délégué de l'application de

- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {    

    return ...;
}

C'est vraiment assez simple.

Comment déterminer quand devons-nous autoriser le mode Portrait ou Paysage, etc. - c'est à vous de décider. Tester avec le contrôleur racine n'a pas fonctionné pour moi en raison de certains points, mais cela fonctionne:

- (NSUInteger) application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {    

    return self.fullScreenVideoIsPlaying ?
        UIInterfaceOrientationMaskAllButUpsideDown :
        UIInterfaceOrientationMaskPortrait;
}

La propriété "fullScreenVideoIsPlaying" est définie manuellement par moi chaque fois que j'en ai besoin.

L'autre chose importante à prendre en compte est l'énumération. Comme cela est dit dans la documentation ... (lisez attentivement ce qui concerne l'iPad/l'iPhone ci-dessus). Ainsi, vous pouvez jouer avec cela selon vos besoins.

Un autre petit problème était un comportement bogué après la fermeture du lecteur vidéo. Il y a eu une fois où il n'a pas changé l'orientation, mais c'est arrivé une seule fois et de manière étrange, et uniquement dans le simulateur (iOS 6 seulement, bien sûr). Donc, je ne pouvais même pas réagir, car cela est arrivé de manière inattendue et après avoir cliqué rapidement sur d'autres éléments de mon application, il est revenu à l'orientation normale. Donc, je ne suis pas certain - cela pourrait être un retard dans le fonctionnement du simulateur ou quelque chose d'autre (ou vraiment un bug :) ).

Bonne chance!

7voto

Vipin Johney Points 103

J'ai eu le même problème avec mon application.

Comment fonctionne la rotation sous iOS 6 est la suivante.

\=> chaque fois que vous utilisez UINavigationCOntroller, la méthode dans AppDelegate

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window    
{
   return 
}

décide de tourner ou non.

\=> lorsque la vue est présentée dans le style de présentation modale, la méthode

- (BOOL)shouldAutorotate

qui se trouve à l'intérieur du contrôleur de vue pour cette vue déclenche la méthode dans l'appDelegate. Et dans le premier cas, appDelegate décide de tourner ou non.

Ma solution ::

Ce que j'ai fait pour la présentation modale était cela. Créé un drapeau dans l'app delegate.

chaque fois que le drapeau est OUI, il tourne en paysage et sinon c'est seulement en portrait.

- (NSUInteger)application:(UIApplication*)application
supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
    if(self.shouldRotate ) //shouldRotate est mon drapeau
    {
        self.shouldRotate = NO;
        return (UIInterfaceOrientationMaskAll);
    }
    return (UIInterfaceOrientationMaskPortrait);
}

Et pour basculer entre les rotations

- (BOOL)shouldAutorotate
{
    YourAppDelegate *mainDelegate = (YourAppDelegate*)[[UIApplication sharedApplication]delegate];
    mainDelegate.shouldRotate = YES;

    return YES;
}

Remarque : Cela fonctionne uniquement pour les vues présentées de façon modale. Utiliser un drapeau n'est pas une bonne pratique de codage.

3voto

Serge Kutny Points 31

Vous pouvez également sous-classer UITabBarController pour demander à ses enfants s'ils doivent effectuer une rotation et quels sont les orientations prises en charge, comme ceci :

@implementation MyTabBarController

-(BOOL)shouldAutorotate
{
    return [self.selectedViewController shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [self.selectedViewController supportedInterfaceOrientations];
}

@end

Ensuite, utilisez simplement votre conteneur personnalisé à la place de celui standard et ça fonctionne ! Je viens de tester.

2voto

Anthony Points 2440

Malheureusement, vous devrez activer toutes les orientations dans votre fichier plist et utiliser supportedInterfaceOrientations sur tous les contrôleurs de vue que vous ne voulez pas faire pivoter. (Dans votre cas, tout sauf le lecteur vidéo.)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X