Question

Mise à jour: Voir ma réponse à cette question. Cela semble être un bug. Un cas de test minimal a été créé et un rapport a été déposé auprès d'Apple. (Fixe à partir de l'iPhone OS 3.1.)

Voici un jeu de réflexion du « Je suis si proche! » département.

J'ai une application iPhone basée sur la barre d'onglets. Chaque onglet dispose d'un UINavigationController avec les suspects habituels (barre de navigation, vue de table ... ce qui peut conduire à une autre VC, etc.).

Maintenant, l'un de ces VCs niveau inférieur doit être utilisé dans Portait et mode paysage. Mais il y a un problème. Dans notre paysage convivial VC shouldAutorotateToInterfaceOrientation: ne sera pas appelé hors-the-box! Que faire?

Voici ce que nous faisons. Dans mon contrôleur barre d'onglets, que j'ai mis en œuvre dans son propre fichier, j'ai ceci:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

Cela finit par la propagation de la demande à mon CV paysage convivial, qui répond également à ce message. Tous mes autres VCs ne mettent pas en œuvre cette méthode, ils vont tout simplement avec l'orientation portrait par défaut.

Problème résolu !!! Yay!

Eh bien, pas tout à fait :. (

On dirait que les choses ne vont pas si bien quand est appelé VC mon paysage convivial à l'intérieur des profondeurs du contrôleur de la barre d'onglet MoreNavigationController .

J'ai décidé de comparer / contraste entre un VC appelé dans un des quatre premiers barre d'onglet UINavigationControllers ... et ce même VC appelé dans le MoreNavigationController . Cela va être un peu ultra-détaillée, donc porter avec moi. Espérons que le jeu par le jeu se révèle utile pour des choses sleuthing sur.

Lorsque les charges d'application, il y a plusieurs premiers appels à la shouldAutorotate de la barre onglet contrôleur ... méthode. Dans ces premiers cas, selectedViewController est nul. Cependant, nous terminons finalement le chargement, l'élément initial onglet est sélectionné, et tout va bien.

Droit

. Tout d'abord, nous allons choisir l'un des quatre premiers éléments de la barre d'onglet et percez jusqu'à notre VC.

Nous sélectionnerons troisième nav élément de la barre, de sorte que le troisième est le contrôleur de navigation. Nous creusons jusqu'à notre VC qui prend en charge la rotation. Une inspection rapide confirme que le parent est en effet le contrôleur troisième de navigation de la vue de la liste des contrôleurs de notre barre d'onglets. Bon!

Faisons tourner l'appareil. Le contrôleur de la barre d'onglet est invité à autorotation (voir le code ci-dessus). Nous observons que selectedViewController est que le contrôleur troisième de navigation, ainsi que les contrôleurs haut du contrôleur de navigation et afficher visible sont tous deux sur notre VC fidèle qui prend en charge la rotation.

Ainsi, le contrôleur de la barre d'onglet transmet le shouldAutorotate un message sur le contrôleur troisième nav ... mais notre VC de rotation convivial obtient finalement le message. (Je ne fais rien de spécial ici. Peut-être que le VC désiré reçoit le message, car il est en haut et / ou VC? Visible) En tout état de cause, nous alternons au paysage, les choses sont redimensionnées, et tout va bien. "Grand succès!"

Maintenant, nous allons frapper ce bouton retour et pop la pile de VC, quitter le mode paysage dans le processus. Le contrôleur de barre d'onglets est interrogé à nouveau.

Le temps d'un peu de côté ici. topViewController pour notre contrôleur de navigation est toujours que la rotation de l'environnement VC, mais visibleViewController est maintenant réglé sur UISnapshotModalViewController ! Il h. Jamais vu celui-ci avant ... mais Erica Sadun a . On dirait qu'il est pour « disparaître contrôleurs de vue ». (Qui dans ce cas est certainement vrai - il est bien disparaître)

Comme je continue à marcher à travers, le VC visible reste aussi instantané, mais le haut VC finalement change à la prochaine VC sur la pile, car mon CV spécial est finalement parti. assez juste.

qui est le scénario whavant tout fonctionne bien.

Maintenant, nous allons essayer le même test, mais cette fois, nous allons aller à la MoreNavigationController (l'élément Plus de barre d'onglets) et percez vers le bas à la même classe de VC comme avant. Dans mon cas, il se trouve être le 7 un dans la liste VC de la barre onglet contrôleur.

Nous entrons dans la VC de rotation au courant et ... cette fois-ci, il se demande de faire tourner directement ! La barre d'onglets Controller est pas a demandé la permission de tourner à tout. Hmm.

Une vérification rapide du parent VC montre qu'il est un MoreNavigationController . OK, cela fait sens.

Maintenant, nous allons essayer de faire tourner l'appareil. RIEN APPELLE SE FAIT . Aucun de nos points d'arrêt se faire frapper. Pas dans notre VC. Pas dans notre contrôleur de barre d'onglets. (Hein?!?!)

O-kaaaay. Faisons pop la pile, retournez dans le même VC et essayer de tourner à nouveau. Bizarre. Maintenant, nous recevons un appel dans la barre d'onglets contrôleur demandant l'autorisation d'autorotation. Ici, le contrôleur sélectionné est notre contrôleur fidèle Nav (# 7), mais cette fois son visibleViewController et topViewController sont SET DE NIL

Une fois que nous continuons d'ici, un mystérieux message apparaît dans la console de débogage:

  

Utilisation de l'animation de rotation à deux étages. À   utiliser la seule étape lisse   animation, cette application doit   supprimer procédé en deux étapes   mises en œuvre.

Mystérieux parce que Je ne suis pas en utilisant l'animation de rotation en deux étapes ! Non SecondHalf variantes de méthode sont en jeu partout dans mon code source.

Hélas, mon CV de rotation est au courant n'a jamais dit que la rotation se produit (même si la rotation ne se produit à l'écran), donc bien sûr mon avis est tout encrassées suite. Mayhem et la tristesse s'ensuivent. : (

Nous ne même pas la peine éclater la pile à ce moment.

Je pense que le point de vue du contrôleur des notes doc au problème possible:

  

Si vous souhaitez effectuer sur mesure   animations lors d'une orientation   changement, vous pouvez le faire dans l'un des deux   façons. changements d'orientation utilisés pour   s'en deux étapes, avec des notifications   se produisant au début, au milieu,   et les points d'extrémité de la rotation.   Cependant, dans l'iPhone OS 3.0, le soutien était   ajoutée pour effectuer l'orientation   les changements dans une étape. En utilisant une étape   changement d'orientation a tendance à être plus rapide   que le procédé en deux étapes est plus âgé et   généralement recommandée pour toute nouvelle   code.

Je me demande si MoreNavigationController est toujours répondre au processus en deux étapes, et est donc trébucher toute tentative d'utiliser le processus en une seule étape? Notez que, si vous répondez aux messages en deux étapes, la variante en une seule étape ne fonctionnera pas (encore une fois, par les docs). Je ne répond pas à eux, mais j'ai quelque chose derrière soupçon se faufiler dans les coulisses IS.

En fait, si je commente la méthode en une seule étape, et d'essayer de répondre à willAnimateSecondHalfOfRotationFromInterfaceOrientation: durée: , I ne obtenir la note de service! Mais ça ne marche toujours pas pop la pile très propre (en termes de visuels). Plus étrange encore: willAnimateFirstHalfOfRotationFromInterfaceOrientation: durée: est pas appelé, même quand j'ai essayé de se faufiler un appel à l'auto (en utilisant le message FirstHalf) shouldAutorotateToInterfaceOrientation: . Il retourne immédiatement au cours d'une trace, comme si je ne même définir. Soupir.

Alors que le jeu est par le jeu.

En résumé, a quiconque géré avec succès la rotation de l'appareil en une seule étape pour un VC invoqué à l'intérieur d'un MoreNavigationController Bar Tab Controller? Les esprits curieux veulent savoir!

Était-ce utile?

La solution

Apple déconseille UITabBarController de sous-classement, donc je l'ai trouvé un moyen facile de gérer autorotation en utilisant les catégories à la place. Il ne résout pas votre bug avec les contrôleurs de vue Mais ..., mais je pense qu'il est un moyen plus Apple convivial de faire le travail (et signifie moins subclassing pour vous).

Pour chaque onglet dans mon autorotation d'application correctement, j'ai défini -shouldAutorotateToInterfaceOrientation: dans mes contrôleurs de vue personnalisée, mais ils sont tous à l'intérieur UINavigationControllers dans un UITabBarController, de sorte que le message ne sera pas envoyé dans la chaîne à mon CV jusqu'à ce que ces deux répondent aussi. J'ai donc ajouté les lignes suivantes à mes fichiers délégué app:

  

Ajouté au fond de MyAppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end
  

Ajouté au fond de MyAppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return YES;
}
@end

Autres conseils

Il semble que nous avons un bug. J'ai créé un test reproductible, minimal, et l'a signalé via Reporter Bug d'Apple ( RADAR problème 7.139.857 ) .

Mise à jour:. Ceci a été corrigé comme l'iPhone OS 3.1

Le problème essentiel est:

  

Voir déjà les contrôleurs sur un   Navigation Controller pile ne pas   recevoir    willAnimateRotationToInterfaceOrientation: durée:   messages lorsqu'un contrôleur barre d'onglets de   « Plus Navigation Controller » est   utiliser.

Ce problème ne pas se produire lorsque les contrôleurs de vue de l'élément de barre d'onglets sont des contrôleurs de vue de base. Seulement quand ils sont des contrôleurs de navigation et uniquement lorsque la hiérarchie de navigation « Plus » est en cours d'utilisation.

Le message de la console (en ce qui concerne l'animation de rotation à deux étages) suggère que quelque chose dans le cadre (Plus le contrôleur de navigation?) Utilise encore une animation en deux étapes, même si une seule étape est maintenant recommandé que l'iPhone OS 3.0.

Cela pourrait expliquer pourquoi willAnimateRotationToInterfaceOrientation: n'est pas appelé dans ce cas particulier. Par vue d'Apple documentation controleur, ce message ne sera pas appelé lorsque deux étapes, les premiers messages d'orientation / seconde moitié sont en cours a répondu à la place.

Une version légèrement modifiée de de réponse Victorb qui permet à chaque contrôleur de vue unique de décider si elle permet une rotation.

Ici comme essentiel pour la copie et bifurquer plus facile

AppDelegate.h

@interface UITabBarController (MyApp)
@end

@interface UINavigationController (MyApp)
@end

AppDelegate.m

@implementation UITabBarController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *selectedVC = [self selectedViewController];
    if ([selectedVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [selectedVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end

@implementation UINavigationController (MyApp) 
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    UIViewController *visibleVC = [self visibleViewController];
    if ([visibleVC respondsToSelector:@selector(shouldAutorotateToInterfaceOrientation:)]) {
        return [visibleVC shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
    }

    //optimistic return - if you want no rotation, you have to specifically tell me!
    return YES;
}
@end
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top