64 votes

Guides de disposition des zones sûres dans les fichiers xib - iOS 10

J'ai commencé à adapter mon application pour iPhone, X et a trouvé un problème dans Interface Builder. La zone de sécurité repères de mise en page sont censés être rétro-compatible, selon l'officiel d'Apple vidéos. J'ai trouvé que cela fonctionne très bien dans les storyboards.

Mais dans mes fichiers XIB, de la zone de sécurité repères de mise en page ne sont pas respectés dans iOS 10.

Ils fonctionnent très bien pour la nouvelle version de l'OS, mais l'iOS 10 appareils semblent se contenter de présumer de la zone de sécurité la distance à zéro (en ignorant la barre d'état de la taille).

Je suis absent toute la configuration requise? Est-il un Xcode bug, et si oui, toutes les solutions connues?

Voici une capture d'écran de la question dans un projet de test (à gauche iOS 10, à droite iOS 11):

safe area alignment on top of the screen

70voto

clarus Points 2350

Il y a quelques problèmes avec la sécurité de la zone de mise en page et la rétrocompatibilité. Voir mon commentaire plus ici.

Vous pourriez être en mesure de contourner les problèmes avec des contraintes supplémentaires comme un 1000 priorité >= 20,0 à superview.top et un 750 priorité == safearea.haut. Si vous avez toujours afficher une barre d'état, qui devrait arranger les choses.

Une meilleure approche serait de séparer les storyboards/xibs pour le pré-iOS 11 et iOS-11 et jusqu'à, en particulier si vous avez plus de questions que cela. La raison qui est préférable est parce pré-iOS 11, contrainte de mise en page vers le haut/bas repères de mise en page, mais pour iOS 11 vous devez les déposer à des endroits sûrs. Repères de mise en page sont partis. La pose de repères de mise en page pour le pré-iOS 11 est stylistiquement mieux que la compensation par un min de 20 pixels, même si le résultat sera le même FORUM vous toujours afficher une barre d'état.

Si vous prenez cette approche, vous aurez besoin de mettre chaque fichier à la bonne cible de déploiement qu'il sera utilisé sur iOS (11, ou quelque chose plus tôt), de sorte que Xcode ne vous donne pas mises en garde et vous permet d'utiliser la mise en page des guides ou des zones de sécurité, en fonction. Dans votre code, vérifier pour iOS 11 au moment de l'exécution et de la charge appropriées de la table de montage séquentiel/xibs.

L'inconvénient de cette approche est celui de l'entretien (vous aurez deux ensembles de vos contrôleurs de vue de maintenir et de conserver la synchronisation), mais une fois que votre application prend en charge uniquement iOS 11+ ou Apple corrige la compatibilité descendante guide de présentation de l'contrainte de génération, vous pouvez vous débarrasser de la pré-iOS 11 versions.

Au fait, comment êtes-vous afficher le contrôleur que vous voyez ceci? C'est juste de la vue racine contrôleur ou avez-vous le présenter, ou..? Le problème que j'ai remarqué a à voir avec le poussant vue de contrôleurs, de sorte que vous pouvez frapper un cas différent.

14voto

Martin Massera Points 515

Actuellement, la compatibilité en amont ne fonctionne pas bien.

Ma solution consiste à créer 2 contraintes dans le générateur d'interface et à en supprimer une en fonction de la version d'ios que vous utilisez:

  • pour ios 11: view.top == safe area.top
  • pour les versions antérieures: view.top == superview.top + 20

Ajoutez les deux comme points de vente en tant que myConstraintSAFEAREA et myConstraintSUPERVIEW respectivement. Ensuite:

 override func viewDidLoad() {
    if #available(iOS 11.0, *) {
        view.removeConstraint(myConstraintSUPERVIEW)
    } else {
        view.removeConstraint(myConstraintSAFEAREA)
    }
}
 

5voto

Falco Winkler Points 405

Pour moi, une solution simple pour la faire fonctionner sur les deux versions a été

    if #available(iOS 11, *) {}
    else {
        self.edgesForExtendedLayout = []
    }

À partir de la documentation: "Dans iOS 10 et les versions antérieures, utilisez cette propriété pour signaler les bords de votre point de vue contrôleur étendre en dessous des barres de navigation ou autres fournies par le système de vues. ". Donc, à un tableau vide permet de s'assurer de la vue-contrôleur ne pas s'étendre en dessous des barres de navigation.

Docu est disponible ici

2voto

Tumata Points 787

J'ai combiné les réponses à partir de cette page dans cette, qui fonctionne comme un charme (uniquement pour le haut de page, comme demandé dans la question):

  1. Assurez-vous d'utiliser la zone de sécurité dans votre scénario ou un fichier xib
  2. Contrainte de votre point de vue pour les zones de sécurité
  3. Pour chaque view qui a constraint attaché à la SafeArea.top
    • Créer un IBOutlet pour l' view
    • Créer un IBOutler pour l' constraint
  4. À l'intérieur de la ViewController sur viewDidLoad:

    if (@available(iOS 11.0, *)) {}
    else {
        // For each view and constraint do:
        [self.view.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor].active = YES;
        self.constraint.active = NO;
    }
    

Edit:

Ici est la version améliorée j'ai fini par utiliser dans notre base de code. Il suffit de copier/coller le code ci-dessous et vous connecter chaque vue et les contraintes de leur IBOutletCollection.

@property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *constraintsAttachedToSafeAreaTop;
@property (strong, nonatomic) IBOutletCollection(UIView) NSArray *viewsAttachedToSafeAreaTop;


if (@available(iOS 11.0, *)) {}
else {
    for (UIView *viewAttachedToSafeAreaTop in self.viewsAttachedToSafeAreaTop) {
        [viewAttachedToSafeAreaTop.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor].active = YES;
    }
    for (NSLayoutConstraint *constraintAttachedToSafeAreaTop in self.constraintsAttachedToSafeAreaTop) {
        constraintAttachedToSafeAreaTop.active = NO;
    }
}

Le comte de chaque IBOutletCollection doit être égal. par exemple, pour chaque vue il devrait y être associé contrainte

0voto

Jonny Points 2898

J'ai fini par supprimer la contrainte sur la zone sécurisée que j'avais dans mon fichier xib. Au lieu de cela, j'ai créé un point de vente pour UIView en question et, à partir du code, je l'ai branché comme ceci, dans viewDidLayoutSubviews.

 let constraint = alert.viewContents.topAnchor.constraint(equalTo: self.topLayoutGuide.bottomAnchor, constant: 0)
constraint.priority = 998
constraint.isActive = true
 

Ceci lie une petite "alerte" au haut de l'écran mais garantit que le contenu affiché dans l'alerte est toujours situé sous la zone de sécurité supérieure (iOS11ish) / topLayoutGuide (iOS10ish).

Une solution simple et unique. Si quelque chose se brise, je serai de retour

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