iOS 11 de la zone de sécurité guide de présentation de rétro-compatibilité

Est l'activation de la Zone de Sécurité repères de Mise en page compatible pour iOS en dessous de 11?

enter image description here

51
demandé sur Krunal 2017-09-12 22:42:07

12 réponses

j'ai réussi à travailler avec les nouveaux guides D'aménagement des zones de sécurité et à maintenir la compatibilité avec iOS 9 et iOS 10: (EDIT: comme l'a souligné dans les commentaires de @NickEntin, cette mise en œuvre présumer qu'il y a une barre d'état présents, ce qui ne sera pas vrai dans le paysage sur l'iPhone X. Résultant de l'espace vers le haut (20 points). Il va fonctionner parfaitement bien cependant.

E. G. si vous voulez qu'une vue soit 10 points en dessous du statut barre (et 10 points en dessous du boîtier du capteur sur iPhone X):

  1. dans votre XIB, allez à File Inspector et activez le coffre-fort sont en cochant Use Safe Area Layout Guides .
  2. crée une contrainte du haut de la vue au haut de la vue principale, avec >= (plus grande ou égale) contrainte, constante 30 (30 parce que nous voulons 10 points d'espacement à la barre d'état qui est de 20 points de haut) et la priorité High (750).
  3. Créer une contrainte du haut de la vue au haut de la zone de sécurité, avec = contrainte (égale), constante 10 et priorité Low (250).

la même chose peut être faite pour une vue en bas (et pour conduire/suivre ou Gauche/Droite à la zone de sécurité):

  1. dans votre XIB, allez à File Inspector et activez le coffre-fort sont en cochant Use Safe Area Layout Guides .
  2. créer une contrainte à partir de la vue du bas vers le bas de la vue principale, avec la contrainte >= (supérieure ou égale), constante 10 et priorité High (750).
  3. crée une contrainte du fond de la vue au fond de L'aire de sécurité, avec = contrainte (égale), constante 10 et priorité Low (250).
48
répondu thijsonline 2017-12-20 09:36:43

la rétrocompatibilité des zones de sécurité pour iOS 9 et iOS 10 ne fonctionne que si vous utilisez des storyboards. Si vous utilisez xibs, il n'existe pas de guide de présentation de retomber. https://forums.developer.apple.com/thread/87329

Les solutions semblent être, soit

(a) la migration de votre xibs dans les storyboards, ou

(b) ajouter des contraintes supplémentaires par programmation.

si (a) n'est pas vraiment une option, l'approche manuelle sera quelque chose comme ceci:

en supposant que vous avez une vue dans votre xib que vous voulez garder dans la zone de sécurité (c.-à-d. Sous n'importe quelle barre d'état ou barre de navigation).

  1. ajouter des contraintes dans votre xib entre votre vue et la zone de sécurité pour iOS 11. Attribuer la contrainte supérieure à une priorité de 750.

    add a top constraint

  2. dans votre contrôleur de vue, ajouter une propriété:

    @property (nonatomic, strong) NSLayoutConstraint *topLayoutConstraint;
    

    et puis en viewDidLayoutSubviews:

    - (void)viewDidLayoutSubviews {
        [super viewDidLayoutSubviews];
    
        if (@available(iOS 11, *)) {
            // safe area constraints already set
        }
        else {
            if (!self.topLayoutConstraint) {
                self.topLayoutConstraint = [self.<yourview>.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor];
                [self.topLayoutConstraint setActive:YES];
            }
        }
    }
    

    la nouvelle contrainte ne sera créée que pour iOS 9 & iOS 10, a une priorité par défaut de 1000, et supplante celle du xib.

  3. répéter pour une contrainte de fond si vous devez éviter l'indicateur de maison.

Swift 4 version:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if #available(iOS 11, *) {
        // safe area constraints already set
    } else {
        if topLayoutConstraint == nil {
            topLayoutConstraint = <yourview>.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor)
            topLayoutConstraint?.isActive = true
        }
    }
}
38
répondu Dobster 2018-02-25 22:57:36

il y a certainement au moins un problème de rétrocompatibilité avec les contraintes de zones de sécurité de iOS 11 que j'ai observé dans les contrôleurs Xcode 9 GM--vue poussée avec des contraintes de zones de sécurité.

si votre barre de navigation est cachée et que vous appuyez sur une zone sûre vue TOP-constrained, la vue poussée chevauchera la barre d'état sur iOS 9 & 10.

si la barre de navigation est visible, et" sous les barres supérieures " désactivé, la vue poussée sera encore glisser vers le haut sous la barre de navigation pour atteindre le haut de l'écran. La barre de navigation est placée correctement.

sur iOS 11, la mise en page sera correcte dans les deux cas.

voici un exemple simple: http://www.filedropper.com/foobar

et voici une vidéo de lui W / nav barre cachée (iOS 10.3 à gauche, iOS 11 à droite): https://vimeo.com/234174841/1e27a96a87

voici un version où la barre de navigation est visible (activée dans la nib): https://vimeo.com/234316256/f022132d57

Je l'ai enregistré sous le numéro de Radar 34477706.

merci à @Sander pour avoir pointé le cas visible de la barre de navigation.

18
répondu clarus 2017-09-18 13:15:00

si vous utilisez xibs sans storyboard, il n'y a pas de guide de mise en page sur ios 10. Donc déplacez xib vers storyboard pour avoir une compatibilité arrière.

7
répondu ihar 2017-10-25 08:00:13

Oui, votre projet / application fonctionnera en version iOS avant iOS 11 sans aucun problème. Dans les versions iOS antérieures à 11, Il remplace / considère la disposition des zones de sécurité dans L'AutoLayout normal et suit les règles de top et de Bottom layout guide.

j'ai testé mon projet existant avec et sans "SafeAreaLayout" sur les deux plateformes (iOS 11 et backward iOS 10). Ça fonctionne très bien.

assurez-vous Simplement:

  • si vous avez conçu votre Interface projet/Utilisateur en AutoLayout; les contraintes de votre équipement suivent/relatives au haut et au bas guide de mise en page (pas à superview). Donc, par un simple clic (activer) sur Option SafeAreaLayout, implémente automatiquement Layout SafeArea correctement pour tous les dossiers de constructeurs D'Interface dans votre storyboard.

  • si vous avez conçu votre projet/interface utilisateur dans SafeAreaLayout; alors il sera automatiquement suivez le guide de mise en page en haut et en bas en arrière iOS.

voici un exemple d'instantané avec le résultat, en activant ou désactivant la disposition de la zone de sécurité, n'aura pas d'effet sur la conception existante.

Plan De L'Aire De Sécurité: enter image description here

mise en forme automatique

enter image description here

en bref, une réponse à votre question Est: "permettre des guides de mise en page des zones de sécurité compatibles avec iOS avant 11"



vous pouvez mettre en œuvre la disposition des zones de sécurité dans votre projet / Application et il fonctionnera très bien avec les versions précédentes d'iOS par conversion de la disposition des zones de sécurité en la disposition du haut et du bas.

7
répondu Krunal 2017-12-13 16:21:47

Je l'utilisais dans Objectif-C avec un bon résultat pour iOS 10. Dans le cas où vous utilisez SafeArea dans votre xib, vous pouvez ajouter dans votre viewDidLoad :

if (@available(iOS 11.0, *)) {}
else {
    self.edgesForExtendedLayout = UIRectEdgeNone;
}
4
répondu Dmitry A. 2018-05-25 18:48:10

"zone de sécurité guide de présentation de l'" est rétro-compatible. Eh bien, à moins que vous l'utilisez dans xib. Avec storyboard, ça a l'air bien.

j'ai résolu mon problème en accédant à la" top layout constraint " à partir du premier objet en haut de ma vue.

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *topLayoutConstraint;

ensuite, j'ai changé la valeur constante à cette contrainte et rafraîchit la vue. Par exemple, si vous utilisez une barre de navigation (Hauteur 44) plus la barre d'état (Hauteur 20):

if (SYSTEM_VERSION_LESS_THAN(@"11.0")) {
    _topLayoutConstraint.constant = 64;
    [self.view layoutIfNeeded];
}

avec SYSTEM_VERSION_LESS_THAN qui est défini comme ceci:

#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
3
répondu gduh 2017-11-17 10:12:04

j'ai des problèmes de compatibilité descendante avec WKWebView Et de la Zone de Sécurité sur iOS 9. Pour une raison ou une autre, WKWebView ne tient pas compte des paramètres d'aménagement des zones de sécurité.

2
répondu Nik 2017-09-18 12:36:59

en Objectif - C pour marge supérieure et inférieure sur iPhone-X

if (@available(iOS 11, *)) {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                              attribute:NSLayoutAttributeBottom
                                                                              relatedBy:NSLayoutRelationEqual
                                                                                 toItem:self.parentView.safeAreaLayoutGuide
                                                                              attribute:NSLayoutAttributeBottom
                                                                             multiplier:1.0
                                                                               constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView.safeAreaLayoutGuide
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];


} else {

    NSLayoutConstraint *bottomConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                          attribute:NSLayoutAttributeBottom
                                                                          relatedBy:NSLayoutRelationEqual
                                                                             toItem:self.parentView
                                                                          attribute:NSLayoutAttributeBottom
                                                                         multiplier:1.0
                                                                           constant:0];


    NSLayoutConstraint *topConstraint   = [NSLayoutConstraint constraintWithItem:self.childView
                                                                       attribute:NSLayoutAttributeTop
                                                                       relatedBy:NSLayoutRelationEqual
                                                                          toItem:self.parentView
                                                                       attribute:NSLayoutAttributeTop
                                                                      multiplier:1.0
                                                                        constant:0];

}
2
répondu Chandan 2017-10-04 11:04:36

voici ce que j'ai fait avec mes projets

dans mon cas, mes topConstraint et bottomConstraint s sont @IBOutlet S. C'est aussi compatible pour iOS 8 .

ma configuration initiale pour les contraintes du haut et du bas est pour les iPhones normaux, c'est pourquoi je ne édite que les contraintes pour iPhone X

    // iOS 11 Layout Fix. (For iPhone X)
    if #available(iOS 11, *) {
        self.topConstraint.constant = self.topConstraint.constant + self.view.safeAreaInsets.top

        self.bottomConstraint.constant = self.bottomConstraint.constant + self.view.safeAreaInsets.bottom
    }

.

NOTE: self.view est votre superView c'est pourquoi je l'utilise pour safeAreaInsets

2
répondu Zonily Jame 2018-01-16 04:34:49

lorsque vous avez un ViewController générique que tous vos ViewControllers étendent, une autre solution serait de mettre les éléments qui doivent être ajustés dans une Collecti on Iboutletet et de les ajuster programmatiquement dans ce ViewController Générique. Voici mon code:

@IBOutlet var adjustTopSpaceViews: [UIView]?

override func viewDidLoad() {
    super.viewDidLoad()
    adjustViews()
    ....
}

func adjustViews() {
    guard let views = adjustTopSpaceViews,
        ProcessInfo.processInfo.operatingSystemVersion.majorVersion < 11 else {
            return
    }
    let statusBarHeight = UIApplication.shared.statusBarFrame.height
    for subview in views {
        subview.superview?.constraints.filter({ (constraint) -> Bool in
            return constraint.firstAttribute == .top
                && constraint.secondAttribute == .top
                && (constraint.firstItem as? UIView == subview || constraint.secondItem as? UIView == subview)
        }).forEach({ (constraint) in
            constraint.constant += (constraint.firstItem as? UIView == subview) ? statusBarHeight : -statusBarHeight
        })
    }
}
2
répondu Youssef MAHERZI 2018-04-27 16:25:47

j'ai trouvé un moyen plus pratique où vous avez seulement besoin de sous-classe le NSLayoutConstraint qui est épinglé à votre safeArea .

c'est un peu hacky puisque vous devez obtenir le ViewController à partir d'un uivi, mais à mon avis, c'est une alternative facile et bonne jusqu'à ce Qu'Apple corrige enfin la compatibilité en arrière pour la zone de sécurité dans Xibs.

sous-classe:

class SafeAreaBackwardsCompatabilityConstraint: NSLayoutConstraint {
private weak var newConstraint: NSLayoutConstraint?

override var secondItem: AnyObject? {
    get {
        if #available(iOS 11.0, *) {}
        else {
            if let vc = (super.secondItem as? UIView)?.parentViewController, newConstraint == nil {
                newConstraint = (self.firstItem as? UIView)?.topAnchor.constraint(equalTo: vc.topLayoutGuide.bottomAnchor)
                newConstraint?.isActive = true
                newConstraint?.constant = self.constant
            }
        }
        return super.secondItem
    }
}

override var priority: UILayoutPriority {
    get {
        if #available(iOS 11.0, *) { return super.priority }
        else { return 750 }
    }
    set { super.priority = newValue }
}
}

private extension UIView {
var parentViewController: UIViewController? {
    var parentResponder: UIResponder? = self
    while parentResponder != nil {
        parentResponder = parentResponder!.next
        if let viewController = parentResponder as? UIViewController {
            return viewController
        }
    }
    return nil
}
}

Xib:

enter image description here

2
répondu iVentis 2018-09-03 08:13:31