web-dev-qa-db-fra.com

Autorotate dans iOS 6 a un comportement étrange

J'ai l'application UITabBarController qui lit la vidéo et affiche d'autres informations dans d'autres onglets UITabBar. Dans iOS 6 UIView les méthodes de rotation sont obsolètes, et maintenant je dois utiliser les méthodes shouldAutoRotate et supportedInterfaceOrientations. Pour la lecture de vidéos, j'utilise MPMoviePlayerViewController.

Comment faire pivoter uniquement cette vue de joueur? Je ne peux faire pivoter que l'application entière, mais je ne veux pas le faire. Je présente MPMoviePlayerViewController mais il ne tourne pas comme dans iOS 5 et versions antérieures.

Dans le paramètre plist, je n'ai défini qu'une seule orientation d'interface Portrait. Si je mets un autre - toute l'application sera tournée.

28
Timur Mustafaev

À partir des notes de mise à jour du SDK iOS 6 d'Apple:

L'autorotation change dans iOS 6. Dans iOS 6, la méthode shouldAutorotateToInterfaceOrientation: de UIViewController est déconseillée. À sa place, vous devez utiliser les méthodes supportedInterfaceOrientationsForWindow: et shouldAutorotate.

Plus de responsabilités se déplacent vers l'application et le délégué de l'application. Désormais, les conteneurs iOS (tels que 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 par une application et un contrôleur de vue sont définies sur UIInterfaceOrientationMaskAll pour l'idiome iPad et UIInterfaceOrientationMaskAllButUpsideDown pour l'idiome iPhone.

Les orientations d'interface prises en charge par un contrôleur de vue peuvent changer au fil du temps, même les orientations d'interface prises en charge par une application peuvent changer au fil du temps. Le système demande au contrôleur de vue plein écran le plus haut (généralement le contrôleur de vue racine) les orientations d'interface prises en charge chaque fois que l'appareil tourne ou lorsqu'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 OUI à partir de sa méthode shouldAutorotate. Le système coupe les orientations prises en charge par le contrôleur de vue avec les orientations prises en charge par l'application (telles que déterminées par le fichier Info.plist ou l'application du délégué d'application: supportedInterfaceOrientationsForWindow: méthode) pour déterminer s'il faut faire pivoter.

Le système détermine si une orientation est prise en charge en coupant 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 plein écran le plus haut. La méthode setStatusBarOrientation: animated: n'est pas complètement obsolète. Cela ne fonctionne désormais que si la méthode prise en chargeInterfaceOrientations du contrôleur de vue plein écran le plus haut renvoie 0. Cela rend l'appelant responsable de la cohérence de l'orientation de la barre d'état.

Pour des raisons de compatibilité, les contrôleurs de vue qui implémentent toujours la méthode shouldAutorotateToInterfaceOrientation: n'obtiennent pas les nouveaux comportements d'autorotation. (En d'autres termes, ils ne recourent pas à l'utilisation de l'application, du délégué d'application ou du 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 toute votre application tourne, vous devez configurer votre 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 faire une sorte de sous-classe et remplacer les méthodes d'autorotation pour retourner uniquement en mode portrait. J'ai un exemple ici:

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

45
rocky

Ough! Une demi-journée passée et le problème résolu! Il lui.

Comme le dit la documentation ci-dessus, c'est vraiment ça! Les points essentiels sont:

Plus la responsabilité se déplace vers l'application et le délégué de l'application. Désormais, les conteneurs iOS (tels que 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 par une application et un contrôleur de vue sont définies sur UIInterfaceOrientationMaskAll pour l'idiome iPad et UIInterfaceOrientationMaskAllButUpsideDown pour l'idiome iPhone.

Donc, à chaque fois que quelque chose change avec le contrôleur racine, le système demande au délégué de l'application "Alors, que sommes-nous? En rotation ou non?"

Si "en rotation":

les orientations prises en charge ne sont récupérées que si ce contrôleur de vue renvoie OUI à partir de sa méthode shouldAutorotate

alors le système demande à notre délégué d'application

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

    return ...;
}

C'est vraiment assez simple.

Comment déterminer quand devrions-nous autoriser Portrait ou Paysage, etc. - c'est à vous de décider. Le test du contrôleur racine n'a pas fonctionné pour moi à cause de certains points, mais cela fonctionne:

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

    return self.fullScreenVideoIsPlaying ?
        UIInterfaceOrientationMaskAllButUpsideDown :
        UIInterfaceOrientationMaskPortrait;
}

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

La seule autre chose importante à faire attention est l'énumération. Comme il est dit dans les documents ... (lire attentivement au-dessus de l'iPad/iPhone). Ainsi, vous pouvez jouer avec ceux dont vous avez besoin.

Une autre petite chose était un comportement buggé après la fermeture du contrôleur du lecteur. Il fut un temps où cela ne changeait pas l'orientation, mais cela s'est produit une fois et de manière étrange, et uniquement dans le simulateur (iOS 6 uniquement, bien sûr). Donc, je n'ai même pas pu réagir, car cela s'est produit de manière inattendue et après avoir cliqué rapidement sur d'autres éléments de mon application, il a tourné en orientation normale. Donc, je ne sais pas - cela pourrait être un certain retard dans le travail du simulateur ou quelque chose (ou, vraiment un bug :)).

Bonne chance!

13
Agat

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

Comment fonctionne la rotation dans iOS 6?.

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

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

décide de faire pivoter ou non.

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

- (BOOL)shouldAutorotate

qui est à l'intérieur du viewController pour cette vue déclenche la méthode dans l'appDelegate. Et comme 1er cas, appDelegate décide de tourner ou non.

Ma solution ::

Ce que j'ai fait pour la présentation Modal, c'est ça. Créé un indicateur dans le délégué de l'application.

chaque fois que le drapeau est OUI, il tourne en paysage et sinon en son seul portrait.

- (NSUInteger)application:(UIApplication*)application
supportedInterfaceOrientationsForWindow:(UIWindow*)window
{
    if(self.shouldRotate ) //shouldRotate is my flag
    {
        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 qui sont modérément présentées. Utiliser Flag n'est pas une bonne pratique de codage.

7
Vipin Johney

Vous pouvez également sous-classer UITabBarController pour lui demander de demander à ses enfants des informations sur shouldAutorotate et supportedInterfaceOrientation comme ceci:

@implementation MyTabBarController

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

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

@end

Ensuite, vous utilisez simplement votre conteneur personnalisé à la place du conteneur standard et cela fonctionne! vient d'être testé.

3
Serge Kutny

Malheureusement, vous devrez activer toutes les orientations dans votre liste et utiliser lesInterfaceOrientations prises en charge sur tous les contrôleurs de vue que vous ne souhaitez pas faire pivoter. (Dans votre cas, tout sauf le lecteur vidéo.)

2
Anthony

Essaye ça,

Si TabBarController est RootViewController pour fenêtre, alors créez une classe personnalisée qui hérite de TabBarController, dites CustomTabBarController.h

Ajouter la méthode ci-dessous dans CustomTabBarController.h

-(NSUInteger)supportedInterfaceOrientations // Must return Orientation Mask

Enfin, appelez ci-dessous dans AppDelegate.m

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  {
   if( [self.window.rootViewController supportedInterfaceOrientations]!=0) 
     {
        return [self.window.rootViewController supportedInterfaceOrientations];
    }
    return UIInterfaceOrientationMaskAll;
}
1
Vinay

J'ai trouvé que la façon la plus simple de configurer cela était d'utiliser les boutons "Orientations d'interface prises en charge" que vous pouvez voir si vous regardez Targets .... Onglet Summary (sous iPhone/iPad Deployment info).

C'est essentiellement une interface graphique pour définir le fichier plist

0
Tim