Mon application a 2 écrans:
TableViewVC (pas de vues de pile ici)
DetailVC (toutes les vues de pile imbriquées ici; veuillez consulter le lien pour l'image: Image imbriquée de StackViews ) - Veuillez noter qu'il existe des étiquettes et des images dans ces vues de pile.
Lorsque vous appuyez sur une cellule de la vue table, les informations de TableViewVC sont transmises à DetailVC. Le problème est que masque les vues UIStackViews spécifiques dans DetailVC. Je souhaite que seulement 2 vues de pile parmi les différentes vues de DetailVC soient masquées dès le chargement de la vue. Donc j'écris ce code dans le DetailVC pour accomplir ceci:
override func viewDidLoad() {
super.viewDidLoad()
self.nameLabel.text = "John"
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
}
Tout a l'air génial, mais Xcode donne beaucoup d'avertissements uniquement à runtime Storyboard n'émet aucun avertissement lorsque l'application n'est pas en cours d'exécution. S'il vous plaît voir le lien pour l'image des erreurs: Image des erreurs
Fondamentalement, il y a beaucoup d'erreurs de connexion UISV, de masquage UISV, d'espacement UISV. Ces erreurs disparaissent si je cache les mêmes vues de pile dans viewDidAppear
, mais il y a alors un éclair de la substance qui était censée être cachée, puis il se cache. L'utilisateur voit brièvement la vue puis se cache, ce qui n'est pas bien.
Désolé de ne pas pouvoir publier de photos au lieu de liens, je ne peux toujours pas le faire.
Des suggestions sur la façon de résoudre ce problème? Ceci est pour une application que je veux réellement lancer sur l'App Store - c'est ma première fois alors toute aide serait géniale!
Edition/Mise à jour 1:
J'ai trouvé un petit problème avec ce code que j'ai mis dans le deuxième écran appelé DetailVC:
// Function I use to delay hiding of views
func delay(delay: Double, closure: ()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue(), closure)
}
// Hide the 2 stack views after 0.0001 seconds of screen loading
override func awakeFromNib() {
delay(0.001) { () -> () in
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
}
}
// Update view screen elements after 0.1 seconds in viewWillAppear
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
delay(0.1) { () -> () in
self.nameLabel.text = "John"
}
}
Cela supprime complètement les avertissements concernant les contraintes de mise en page de Xcode.
Ce n'est pas encore parfait, car parfois, je vois un aperçu des points de vue censés être cachés - ils clignotent très rapidement sur l'écran puis disparaissent. Cela arrive si vite cependant.
Des suggestions quant à pourquoi cela supprime les avertissements? En outre, toutes les suggestions sur la façon d'améliorer ceci fonctionnent-elles parfaitement??? Merci!
Avez-vous essayé cela, appeler le super après vos changements?
override func viewWillAppear() {
self.nameLabel.text = "John"
self.summaryStackView.hidden = true
self.combinedStackView.hidden = true
super.viewWillAppear()
}
J'ai eu le même problème et je l'ai résolu en donnant la priorité à 999 aux contraintes de hauteur de mes vues initialement masquées.
Le problème est que votre stackview applique une contrainte de hauteur de 0 sur votre vue masquée, ce qui est en conflit avec votre autre contrainte de hauteur. C'était le message d'erreur:
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x7fa3a5004310 V:[App.DummyView:0x7fa3a5003fd0(40)]>",
"<NSLayoutConstraint:0x7fa3a3e44190 'UISV-hiding' V:[App.DummyView:0x7fa3a5003fd0(0)]>"
)
Donner à votre contrainte de hauteur une priorité inférieure résout ce problème.
Il s'agit d'un problème connu lié au masquage des vues de pile imbriquées.
Il y a essentiellement 3 solutions à ce problème:
innerStackView.removeFromSuperview()
, mais vous devrez alors vous rappeler où insérer la vue de pile.La 3ème option est la meilleure à mon avis. Pour plus d'informations sur ce problème, pourquoi cela se produit-il, les différentes solutions et comment implémenter la solution 3, voir ma réponse à une question similaire .
Vous pouvez utiliser les propriétés removeArrangedSubview et removeFromSuperview de UIStackView.
En Objective-C:
[self.topStackView removeArrangedSubview:self.summaryStackView];
[self.summaryStackView removeFromSuperview];
[self.topStackView removeArrangedSubview:self.combinedStackView];
[self.combinedStackView removeFromSuperview];
De la documentation Apple UIStackView: ( https://developer.Apple.com/library/ios/documentation/UIKit/Reference/UIStackView_Class_Reference/#//Apple_ref/occ/instm/UIStackView/removeArrangedSubview :)
La vue de pile met automatiquement à jour sa mise en page chaque fois que des vues sont ajoutées, supprimées ou insérées dans le tableau arrangSubviews.
Pour empêcher la vue d’apparaître à l’écran après l’appel de la méthode removeArrangedSubview: de la pile, supprimez explicitement la vue du tableau de sous-vues en appelant la méthode removeFromSuperview de la vue ou définissez la propriété masquée de la vue sur YES.
Lorsque UIViewStack est masqué, les contraintes générées automatiquement par UIStackView émettent de nombreux avertissements de masquage UISV, d'espacement UISV et de connexion UISV-canvas, si la propriété d'espacement d'UIStackView a une valeur autre que zéro.
Cela n'a pas beaucoup de sens, c'est presque certainement un bug du framework. La solution de contournement que j’utilise consiste à définir l’espacement à zéro lors du masquage du composant.
if hideStackView {
myStackView.hidden = true
myStackView.spacing = CGFloat(0)
} else {
myStackView.hidden = false
myStackView.spacing = CGFloat(8)
}
J'ai constaté que UIStackViews imbriqué présente ce comportement si vous définissez la propriété masquée dans «Générateur d'interface». Ma solution consistait à définir tout ce qui n'était pas caché dans «Interface Builder» et à masquer certains éléments dans viewWillAppear de manière sélective.
Je l'ai corrigé en mettant les commandes de masquage dans traitCollectionDidChange.
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
self.item.hidden = true
}
Donc, cela ne peut aider que 0,000001% des utilisateurs, mais peut-être s'agit-il d'un problème lié aux clips.
Je me suis heurté récemment à cette situation lorsque je travaillais avec UICollectionViewCell
. J'ai oublié de vérifier les clips jusqu'à la limite que je traitais en tant que vue de contenu. Lorsque vous créez une UITableViewCell
dans IB, elle configure par défaut une vue de contenu avec des clips.
Le fait est que, selon votre situation, vous pourrez peut-être obtenir l'effet que vous souhaitez en utilisant des cadres et des découpages.
J'ai déplacé tout le code UIStackView.hidden de viewDidLoad à viewDidAppear et le problème des contraintes brisées a disparu. Dans mon cas, toutes les contraintes conflictuelles étaient générées automatiquement, donc aucun moyen d’ajuster les priorités.
J'ai aussi utilisé ce code pour le rendre plus joli:
UIView.animateWithDuration(0.5) {
self.deliveryGroup.hidden = self.shipVia != "1"
}
MODIFIER:
Nous avions également besoin du code suivant pour que cela ne se reproduise plus lors de la rotation du périphérique:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
self.deliveryGroup.hidden = false
coordinator.animateAlongsideTransition(nil) {
context in
self.deliveryGroup.hidden = self.shipVia != "1"
}
}
Cette erreur ne concerne pas la dissimulation, mais des contraintes ambiguës. Vous ne devez avoir aucune contrainte ambiguë dans votre vue. Si vous les ajoutez par programme, vous devez comprendre exactement les contraintes que vous ajoutez et leur interaction. ne sont pas des erreurs de contrainte ou des avertissements.
UPD: Vous avez une structure de vues assez complexe ici. Sans voir les contraintes, il est difficile de dire ce qui ne va pas. Cependant, je suggérerais de vous construire une hiérarchie de vues en ajoutant progressivement des vues une par une et en vous assurant qu'il n'y a pas d'avertissements de conception/exécution. La vue défilement peut ajouter un autre niveau de complexité si vous ne la gérez pas correctement. Découvrez comment utiliser les contraintes avec une vue de défilement ... Tous les autres hacks de synchronisation ne sont pas une solution.
Je l'ai fait en stockant toutes les vues cachées de UIStackView imbriqué dans un tableau et en les supprimant de la vue d'ensemble et des sous-vues organisées. Quand je voulais qu'ils apparaissent à nouveau, j'ai parcouru le tableau et les ai rajoutés. C'était la première étape.
La deuxième étape consiste à supprimer les vues de la vue UIStackView imbriquée de la vue d'ensemble, mais le parent UIStackView n'a toujours pas ajusté sa hauteur. Vous pouvez résoudre ce problème en supprimant le UIStackView imbriqué et en l'ajoutant tout de suite après:
UIStackView *myStackView;
NSUInteger positionOfMyStackView = [parentStackView indexOfObject:myStackView];
[parentStackView removeArrangedSubview:myStackView];
[myStackView removeFromSuperview];
[parentStackView insertArrangedSubview:myStackView atIndex:positionOfMyStackView];
Mettez vos commandes hide dans viewWillLayoutSubviews() {}