Je suis en train de mettre à jour mon application pour l'adapter à iPhone X. Tous les affichages fonctionnent correctement, sauf un. J'ai un contrôleur de vue qui présente une UIView personnalisée qui couvre tout l'écran. Avant, j’utilisais UIScreen.main.bounds
pour connaître la taille de la vue avant que toute la mise en page ne soit terminée (j’en ai besoin pour placer le bon itemSize dans une collectionView). Je pensais que je pouvais maintenant faire quelque chose comme UIScreen.main.bounds.size.height - safeAreaInsets.bottom
pour obtenir la bonne taille utilisable. Le problème est que safeAreaInsets renvoie (0,0,0,0) une tentative sur un iPhone X (simulateur). Des idées? Dans d'autres vues, j'obtiens les bons numéros pour safeAreaInsets.
Je vous remercie!
Je trouvais déjà la solution: je faisais toute l'implémentation dans la init
de la vue. safeAreaInsets a la taille correcte dans layoutSubviews()
J'ai récemment eu un problème similaire où les encarts de la zone sécurisée sont renvoyés (0, 0, 0, 0) dès que viewDidLoad est déclenché. Il semble qu'ils soient définis un peu plus tard que le reste du chargement de la vue.
Je l'ai contourné en surchargeant viewSafeAreaInsetsDidChange et en faisant ma mise en page de la manière suivante:
override func viewSafeAreaInsetsDidChange() {
// ... your layout code here
}
J'ai également rencontré ce problème en essayant de déplacer des vues vers le haut pour faire place au clavier de l'iPhone X. Les arrières safeAreaInsets de la vue principale sont toujours 0, même si je sais que les sous-vues ont été définies à cet endroit, à l'écran. a été dessiné. Un travail que j'ai trouvé, comme mentionné ci-dessus, consiste à récupérer la clé KeyWindow et à vérifier ses encarts de zone de sécurité.
Obj-C:
CGFloat bottomInset = [UIApplication sharedApplication].keyWindow.safeAreaInsets.bottom;
Rapide:
let bottomInset = UIApplication.shared.keyWindow?.safeAreaInsets.bottom
Vous pouvez ensuite utiliser cette valeur pour ajuster les contraintes ou afficher les cadres selon les besoins.
J'ai une vue qui est une sous-vue dans une autre vue. J'ai constaté que je ne pouvais pas obtenir correctement safeAreaInsets, il retournait toujours 0, dans cette vue sur iPhoneX, même si je le mettais dans layoutSubviews. La solution finale est d’utiliser l’extension UIScreen suivante pour détecter les safeAreaInsets qui peuvent fonctionner comme un charme.
extension UIScreen {
func widthOfSafeArea() -> CGFloat {
guard let rootView = UIApplication.shared.keyWindow else { return 0 }
if #available(iOS 11.0, *) {
let leftInset = rootView.safeAreaInsets.left
let rightInset = rootView.safeAreaInsets.right
return rootView.bounds.width - leftInset - rightInset
} else {
return rootView.bounds.width
}
}
func heightOfSafeArea() -> CGFloat {
guard let rootView = UIApplication.shared.keyWindow else { return 0 }
if #available(iOS 11.0, *) {
let topInset = rootView.safeAreaInsets.top
let bottomInset = rootView.safeAreaInsets.bottom
return rootView.bounds.height - topInset - bottomInset
} else {
return rootView.bounds.height
}
}
}
la méthode viewDidAppear (_ :) du contrôleur de vue conteneur qui étend la zone sécurisée de son contrôleur de vue enfant intégré pour prendre en compte les vues dans.
Apportez vos modifications dans cette méthode car les encarts de la zone sécurisée pour une vue ne sont pas précis tant que la vue n'est pas ajoutée à une hiérarchie de vues.
override func viewDidAppear(_ animated: Bool) {
if (@available(iOS 11, *)) {
var newSafeArea = view.safeAreaInsets
// Adjust the safe area to accommodate
// the width of the side view.
if let sideViewWidth = sideView?.bounds.size.width {
newSafeArea.right += sideViewWidth
}
// Adjust the safe area to accommodate
// the height of the bottom view.
if let bottomViewHeight = bottomView?.bounds.size.height {
newSafeArea.bottom += bottomViewHeight
}
// Adjust the safe area insets of the
// embedded child view controller.
let child = self.childViewControllers[0]
child.additionalSafeAreaInsets = newSafeArea
}
}
J'ai rencontré le même problème. Dans mon cas, la vue que j'insère sera dimensionnée correctement après l'appel de view.layoutIfNeeded()
. Le view.safeAreaInsets
a été défini après cela, mais seule la valeur top
était correcte. La valeur inférieure était toujours 0
(ceci sur un iPhone X).
Tout en essayant de déterminer à quel moment les safeAreaInsets
sont correctement définis, j'ai ajouté un point d'arrêt à la méthode safeAreaInsetsDidChange()
de la vue. Cela a été appelé plusieurs fois, mais seulement lorsque j'ai vu CALayer.layoutSublayers()
dans la trace, la valeur avait été définie correctement.
J'ai donc remplacé view.layoutIfNeeded()
par le correspondant de CALayer
view.layer.layoutIfNeeded()
, ce qui a permis de régler correctement le safeAreaInsets
, résolvant ainsi mon problème.
TL; DR
Remplacer
view.layoutIfNeeded()
par
view.layer.layoutIfNeeded()
[UIApplication sharedApplication].keyWindow.safeAreaInsets return none zero
Essayez simplement self.view.safeAreaInsets
au lieu de UIApplication.shared.keyWindow?.safeAreaInsets
Les zones insérées ne semblent pas se remplir sur les appareils iOS 11.x.x à la demande via l'application keyWindow.