web-dev-qa-db-fra.com

Segue adaptative dans le storyboard Xcode 6. Push est-il obsolète?

Le constructeur d'interface Xcode 6 a par défaut une nouvelle case à cocher "utiliser des classes de taille". Cela rend les vues adaptatives. enter image description here

Lorsque j'essaie de faire la distinction entre 2 vues dans mon storyboard, j'ai de nouvelles options: enter image description here

à la place vieux:

enter image description here

Nous avons maintenant "show" et "present modally" au lieu de "Push" et "modal". Les anciennes options sont marquées comme obsolètes. J'ai choisi l'option "afficher", car dans les paramètres de séquence, elle s'appelle "afficher (par exemple, Push)".

enter image description here

Mais ça ne fait pas Push. L'animation de la séquence ressemble à une diapositive à partir du bas (modale) et la barre de navigation disparaît.

La question est: Comment puis-je faire "show" travailler comme push? Est-ce possible ou dois-je utiliser "Push (obsolète)" à la place? Où puis-je trouver des informations sur les nouveaux types de segue? La seule chose que j'ai trouvée dans la bibliothèque de développement iOS8 est Storyboards vous aide à concevoir votre interface utilisateur mais il n'y a aucune information à propos de "show" segue.

MISE À JOUR

J'ai essayé de créer un nouveau projet et "show" fonctionne vraiment comme "Push". Je pense que le problème dans mon projet peut être parce que je réutilise le contrôleur de navigation avec un code comme celui-ci, mais je ne sais pas comment le réparer.

if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
    SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;

    swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {

        UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
        [navController setViewControllers: @[dvc] animated: NO ];
        [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
    };

}

Après cela, j'essaie de pousser NewViewController après MainViewController enter image description here

MISE À JOUR 2:

Je semble être que iOS 7, problème iOS 7.1.

119
John Kakon

Oui, utilisez "Show" au lieu de "Push"

Comment puis-je faire "show" travail comme push? Est-ce possible ou devrais-je utiliser plutôt "Push (depricated)"?

Cela devrait; ça le fait pour moi. J’utilise Xcode 6 beta 2 et pour tester j’ai utilisé le modèle de vue unique (en appelant le contrôleur de vue pré-fabriqué dans IB ‘VC_A’). J’ai ensuite ajouté un autre contrôleur de vue (‘VC_B’). J'ai ensuite ajouté un bouton sur VC_A pour afficher VC_B et un autre de VC_B vers VC_A. Lorsque j'ajoute un contrôleur de navigation en tant que contrôleur de vue initial dans le storyboard et que je fais de VC_A le rootViewController, les deux fonctions "Push" et "show" ont le même effet. Si je n’ai pas de contrôleur de navigation initial et que j’utilise "show", j’obtiens ce que vous décrivez dans le fait que le VC_B fait une diapositive vers le haut. Si j’essaie de "Push", je tombe en panne car pour pouvoir le faire, je dois disposer d’un contrôleur de navigation. Il semblerait donc que ‘show’ fera un Push dans le cas où un contrôleur de navigation est fourni et fait un cadeau avec un style de transition modale si aucun contrôleur de navigation n’est présent.

Où puis-je trouver des informations sur les nouveaux types de segue?

J'ai donc trouvé des informations dans la session "Quoi de neuf dans Interface Builder" ici . Si vous regardez les diapositives, vous verrez une diapositive (41) mentionner le changement. Lorsque vous regardez la vidéo de la session, vous pouvez passer à la minute 38:00 où ils commencent à parler de séquences adaptatives. Ils expliquent que le segment adaptatif "show", par exemple, prend en compte le contexte lorsqu’il décide de la présentation d’un nouveau contrôleur de vue.

95
Spencer Hall

Il y a déjà une réponse acceptée, mais je voulais donner un peu plus d'informations, peut-être des informations qui n'étaient pas disponibles auparavant.

Comme il a été mentionné précédemment, les séquences "Push" et "modal" ont été déconseillées et ont été remplacées par "show" et "present modally" respectivement. Selon la documentation d'Apple, les nouvelles divisions ont été divisées en sections adaptées aux classes de taille. Les anciennes versions ne doivent être utilisées que pour prendre en charge les versions iOS antérieures à iOS 8.

Le document dans le lien suivant explique cela et la description de tous les segments disponibles, anciens et nouveaux.

Ajout d'une séquence entre les scènes d'un storyboard

Si l'URL change dans le futur, voici l'explication donnée pour chaque nouvelle séquence:

Spectacle

Présentez le contenu dans la zone de détail ou la zone principale en fonction du contenu de l'écran. Si l'application affiche une vue principale et une vue détaillée, le contenu est placé dans la zone de détail. Si l'application affiche uniquement le maître ou les détails, le contenu est placé au-dessus de la pile de contrôleur de vue actuelle.

Montrer les détails

Présentez le contenu dans la zone de détail. Si l'application affiche une vue principale et une vue détaillée, le nouveau contenu remplace le détail actuel. Si l'application affiche uniquement le maître ou les détails, le contenu remplace le haut de la pile du contrôleur de vue actuel.

Présenter Modalement

Présenter le contenu de manière modale. Il existe des options pour choisir un style de présentation (UIModalPresentationStyle) et un style de transition (UIModalTransitionStyle).

Présent comme Popover

Présentez le contenu sous forme de popover ancré à une vue existante. Il existe une option pour spécifier les directions possibles de la flèche affichée sur un bord de la vue contextuelle (UIPopoverArrowDirection). Il existe également une option pour spécifier la vue d'ancrage.

32
alondono

tldr; Supprimez le Segue qui ne pousse pas correctement et recréez-le dans le story-board en le faisant glisser d'un UIView/UIControl vers le contrôleur de vue cible.

Il n’ya rien de mal avec les autres réponses mais celle-ci explique ce qui se passe, comment vous pouvez vérifier que cela se produit et comment atténuer le problème à l’avenir.

Contexte

Dans mon cas, aucune de mes scènes de spectacle ne fonctionnait alors que j'avais déjà un contrôleur de contrôle UINavigationController (avec mon contenu UIViewController en tant que racine).

Pourquoi et comment le show segue fait une pause

La séquence d'affichage se rompt lorsqu'elle comporte une action associée à la séquence dans le code source XML du storyboard. Cela pourrait être le cas typique si vous avez redéfini une séquence à partir d'une séquence manuelle précédemment appelée dans le code. Cela laisse les bits suivants dans le storyboard xml.

<connections>
    <segue destination="85t-Z1-hxf" kind="show" identifier="ToOptions" action="showDetailViewController:sender:" id="gdZ-IX-KcN">
</connections>

Nota Bene Pour afficher le storyboard au format xml; Cliquez avec le bouton droit sur le fichier de scénario et choisissez Ouvrir en tant que> Code source . Pour revenir en arrière, utilisez Ouvrir en tant que> Interface Builder - Storyboard

Pour prendre en charge toute action personnalisée lors de l'utilisation du segment depuis le storyboard, il suffit de puiser dans prepareForSegue, d'intercepter le contrôleur de vue de destination et d'appeler n'importe quelle méthode à partir de cet emplacement. Dans tous les cas, l’effet secondaire de ce petit bug (le bug, c’est le fait que lorsque vous redéfinissez la séquence, il n’est pas correctement configuré en xml, c’est-à-dire que l’action reste active même après que vous ayez changé la chaîne en opérant depuis UIView (ou UIControl) vers un contrôleur de vue cible).

Malheureusement, la solution la plus directe échoue. Donc, le simple fait de supprimer l'attribut XML pour l'action de l'intérieur du Storyboard résoudra NOT le problème. Au lieu de cela, il faut supprimer et recréer simplement la séquence dans le storyboard.

Une fois recréé, le storyboard xml n'aura plus d'action associée à la séquence particulière et le spectacle s'exécutera en tant que push.

Sample Xml pour Show Show Segue

  <connections>
    <segue destination="RbV-Au-WV9" kind="show" identifier="ToOptions" id="5dm-os-bcS"/>
  </connections>

atténuation

Pour éviter la répétition, il suffit de s'en tenir à des légendes non manuelles du storyboard, en utilisant, si possible, prepareForSegue pour ajouter les actions requises en fonction du contrôleur de vue de destination. Ou bien, si vous devez mélanger et assortir, prenez la précaution pour vérifier que vos actions Show n'ont aucune action associée au storyboard xml. Si vous travaillez avec des projets plus anciens, vous devez accorder une attention particulière au code source de Storyboard, car j'ai découvert quelques problèmes.

23
Tommie C.

Comme Scott Robertson a commenté ici , cela ressemble à un bogue dans iOS 7.

Il semble que dans iOS 8, la transition est inférée au moment de l'exécution (comportement correct), alors que dans iOS 7, elle est inférée au moment de la conception (comportement erroné).

La solution la plus simple consiste à ajouter un contrôleur de navigation inutilisé au storyboard et à le lier de manière à ce que le contrôleur de vue en question fasse partie de ce contrôleur de navigation. Vous n'avez pas réellement besoin d'instancier le contrôleur de navigation, vous avez simplement besoin du contrôleur de vue buggy pour savoir qu'il est intégré dans un contrôleur de navigation.

Remarque: La simulation d'une barre de navigation ne suffit pas à ces fins. vous devez réellement avoir un contrôleur de navigation dans sa pile Push.

Pour reproduire le bogue:

  1. Créez un nouveau storyboard qui utilise des classes de taille.
  2. Créez deux contrôleurs de vue (aucun contrôleur de navigation).
  3. Faites en sorte que le premier contrôleur de vue affiche le deuxième contrôleur de vue via un segment Show (par exemple, Push) lié à un bouton, par exemple.
  4. En code, affichez le premier contrôleur de vue, mais intégrez-le dans un contrôleur de navigation via la méthode initWithRootViewController:.
  5. Exécutez l'application sur iOS 7.
  6. Appuyez sur le bouton qui devrait effectuer le Push.
  7. Vous obtiendrez une transition modale au lieu d'un Push sur iOS 7. Sous iOS 8, vous obtiendrez le comportement Push correct.

enter image description here

Pour corriger le bogue:

  1. Ajoutez un contrôleur de navigation au storyboard et définissez le premier contrôleur de vue sur le contrôleur de vue racine. (Remarque: l'ajout du second en tant que contrôleur de vue racine ne résoudra PAS ce bogue.)
  2. Donnez-lui un identifiant de courrier indésirable pour supprimer l'avertissement indiquant que le contrôleur de navigation est inaccessible et pour vous documenter qu'il existe uniquement en tant que solution de contournement. (par exemple, workaround for show segues in iOS 7).

enter image description here

Notez comment le contrôleur de navigation a été ajouté à la deuxième image et qu’il n’a pas de flèches entrantes (c’est-à-dire qu’il n’ya aucun autre moyen de l’instancier autre que l’identificateur du contrôleur de vue).

20
Senseful

Je sais que je suis en retard mais je voulais partager ce que j'ai appris. C'est en fait un bug et est toujours présent aujourd'hui (2014-12-18).

J'ai écrit un article à ce sujet ici .

Il est facilement reproductible. sous iOS8 fonctionnera parfaitement et même sous iOS7.x tant que vous n’aurez pas poussé un contrôleur de vue dans la pile par programme avant d’appeler la séquence Show.

Si vous appuyez uniquement sur la pile en utilisant des connexions de storyboard, cela fonctionnera; mais apparemment, si vous pressez via le code d'une manière ou d'une autre, la propriété navigationController du poussé UIViewController sera nil et lorsque vous appelez Show, il s'agira d'un modal car il n'y a pas de navigation vers contrôler la pile.

À ce jour, seule la solution de contournement consiste à ne pas utiliser de code Push via un code (non possible) ou à utiliser le code Push, désormais obsolète.

J'ai déposé un radar (lien sur l'article). N'hésitez pas à classer les doublons dans l’espoir de Apple résoudre ce problème.

13
esttorhe

J'ai eu le même problème avec segues dans Xcode 7 et iOS 7.1.2. Show segues (nouvelle fonctionnalité d'iOS 8) fonctionne comme dans iOS 7 et ne vous permet pas de placer vos contrôleurs d'affichage dans la pile de contrôleurs de navigation lorsque vous définissez le type de séquence avec Xcode dans votre Storyboard. C'est pourquoi votre self.navigationController retournera nil, car le contrôleur de vue n'a pas été placé dans la pile et vous ne pouvez pas le faire apparaître.

Je ne comprends pas pourquoi Apple n'a ajouté aucune notification pour ce cas dans Xcode lorsque vous avez besoin que votre application fonctionne sur iOS 7. Ils disent que la méthode Push est obsolète, mais Show ne fonctionne pas correctement avec iOS 7.

Qu'ai-je fait pour résoudre le problème:

J'ai créé la classe MYShowSegue avec .h

#import <UIKit/UIKit.h>

@interface MYShowSegue : UIStoryboardSegue

@end

Et le fichier .m avec un seul effectue la méthode :

#import "MYShowSegue.h"

@implementation MYShowSegue

- (void) perform {

    if ([[[self sourceViewController] navigationController] respondsToSelector:@selector(showViewController:sender:)]) {

        id sender = nil;
        [[[self sourceViewController] navigationController] showViewController:[self destinationViewController] sender:sender];
    }else{

        [[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:YES];
    }
}

@end

Ensuite, vous devez définir un type personnalisé pour chaque séquence de votre Storyboard et sélectionner une nouvelle classe. Dans mon cas, il s'agissait de MYShowSegue.

Exemple de Segue personnalisé

Cette solution vous aidera à obtenir un support complet de vos applications iOS 7, ils utiliseront la méthode pushViewController pour pousser vos vues et pour iOS 8,9, etc. . votre segue fonctionnera avec la nouvelle méthode (iOS 8) showViewController

N'oubliez pas de faire la même chose avec toutes vos ligues dans votre Storyboard.

2
Igor Tikhonov

Cela se produit encore dans iOS 10.x

Supprimer et ré-installer des ligues n'a rien résolu pour moi:

Problème: la fonctionnalité requise était de 7 segments qui fonctionnaient uniquement en tant que "Push" (en fait, un détail de spectacle), mais en fait, seul le premier segment que j’avais ajouté serait Push, les autres se comportaient tous de manière modale. Ceci en dépit d'Interface Builder décrivant chacune des segments de manière identique.

Solution: Je devais ajouter l'action aux 6 secondes qui ne l'avaient pas.

Storyboard XML d'origine

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" id="3NK-93-wTy"/>
</connections>

J'ai changé cela en ajoutant showViewController: sender

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" action="showViewController:sender:" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" action="showViewController:sender:" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" action="showViewController:sender:" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" action="showViewController:sender:" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" action="showViewController:sender:" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" action="showViewController:sender:" id="3NK-93-wTy"/>
</connections>
1
Damo