activateConstraints: et deactivateConstraints: ne pas persister après la rotation pour les contraintes créées dans IB

Les nouvelles methods NSLayoutConstraint activateConstraints: et NSLayoutConstraint deactivateConstraints: ne semblent pas fonctionner correctement avec les contraintes créées par IB (elles fonctionnent correctement pour les contraintes créées par le code). J'ai créé une application de test simple avec un button qui a deux sets de contraintes. Un set, qui est installé, a des contraintes centerX et centerY, et l'autre set, qui est désinstallé, a des contraintes de haut et de gauche (constante 10). La méthode du button bascule ces sets de contraintes. Voici le code,

 @interface ViewController () @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *uninstalledConstraints; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *installedConstraints; @end @implementation ViewController - (IBAction)switchconstraints:(UIButton *)sender { [NSLayoutConstraint deactivateConstraints:self.installedConstraints]; [NSLayoutConstraint activateConstraints:self.uninstalledConstraints]; } -(void)viewWillLayoutSubviews { NSLog(@"installed: %@ uninstalled: %@", ((NSLayoutConstraint *)self.installedConstraints[0]).active ? @"Active" : @"Inactive", ((NSLayoutConstraint *)self.uninstalledConstraints[0]).active ? @"Active" : @"Inactive"); } 

Lorsque l'application se lance, le button est dans la bonne position cinput définie par ses contraintes installées. Après avoir activé / inactivé la méthode d'action du button, le button se déplace correctement vers sa nouvelle position, mais lorsque je l'amène en mode paysage, il revient à sa position initialement définie (même si un journal montre toujours le nouvel set activé être actif). Lorsque je reviens à portrait, le button rest dans sa position initiale (cinput sur l'écran), et maintenant le journal montre que l'set initial de contraintes est actif, et que j'ai activé, comme inactif.

La question est, est-ce un bug, ou ces methods ne sont-elles pas censées fonctionner de cette manière avec les contraintes définies par IB?

Le problème est que vous faites quelque chose d'incohérent avec des contraintes "désinstallées" dans le storyboard. Ils sont là mais pas là. Les contraintes "désinstallées" sont à utiliser uniquement avec les classs de taille! Vous les utilisez si vous voulez que Xcode permute automatiquement les contraintes en rotation. Xcode ne peut pas faire face à ce que vous faites. Mais si vous créez le second set de contraintes dans le code, tout fonctionnera correctement.

Alors fais ça. Supprimez les deux contraintes "désinstallées" et supprimez la sortie uninstalledConstraints . Maintenant, remplacez le code de votre controller de vue complet par ceci:

 @property (strong, nonatomic) NSMutableArray *c1; @property (strong, nonatomic) NSMutableArray *c2; @property (strong, nonatomic) IBOutletCollection(NSLayoutConstraint) NSArray *installedConstraints; @property (weak,nonatomic) IBOutlet UIButton *button; @end @implementation ViewController { BOOL did; } - (void)viewDidLayoutSubviews { NSLog(@"did"); if (!did) { did = YES; self.c1 = [self.installedConstraints mutableCopy]; self.c2 = [NSMutableArray new]; [self.c2 addObject: [NSLayoutConstraint constraintWithItem:self.button atsortingbute:NSLayoutAtsortingbuteTop relatedBy:NSLayoutRelationEqual toItem:self.view atsortingbute:NSLayoutAtsortingbuteTopMargin multiplier:1 constant:30]]; [self.c2 addObject: [NSLayoutConstraint constraintWithItem:self.button atsortingbute:NSLayoutAtsortingbuteLeading relatedBy:NSLayoutRelationEqual toItem:self.view atsortingbute:NSLayoutAtsortingbuteLeadingMargin multiplier:1 constant:30]]; } } - (IBAction)switchconstraints:(UIButton *)sender { [NSLayoutConstraint deactivateConstraints:self.c1]; [NSLayoutConstraint activateConstraints:self.c2]; NSMutableArray* temp = self.c1; self.c1 = self.c2; self.c2 = temp; } 

Appuyez maintenant plusieurs fois sur le button. Comme vous le voyez, il saute entre les deux positions. Maintenant, faites pivoter l'application. le button rest là où il est.

J'ai fait face à une situation similaire.

J'ai créé deux sets de NSLayoutConstraints dans le constructor d'interface. Chaque set pour un cas. Un set a été "installé" l'autre non.

Lorsque je change de casse, l'set de contraintes de layout correspondant est activé et l'autre est désacti- vé. Un tel que décrit dans le Qusteion tournant en avant et en arrière ne fonctionne pas correctement.

Est résolu ceci en installant les deux sets dans le constructor d'interface. Et pour me débarrasser des avertissements, j'ai utilisé une priorité plus faible (999) pour le second set. Cela a fonctionné pour moi.

Btw: Strang j'ai utilisé l'approche "installé / non installé" sur un autre viewcontroller, leur cela a fonctionné.

Dans le cas de non-fonctionnement, le viewcontroller était embedded dans un containerview, peut-être était-ce la raison.

Vous pouvez utiliser ce workflow, même s'il est clair que ce n'est pas un cas d'utilisation pris en charge actuellement pour les gens d'Apple.

L'astuce consiste à ne pas désinstaller les contraintes (comme @matt l'a également souligné), mais à les désactiver dans viewDidLoad() de votre sous-class UIViewController , avant que la layout ne se produise (et vos contraintes conflictuelles causent un problème).

J'utilise cette méthode maintenant et cela fonctionne parfaitement. Idéalement, bien sûr, nous aurions la possibilité de créer visuellement des groupes de contraintes et de les utiliser comme des images keys simplement en les activant et en les désactivant (avec des animations gratuites entre les deux) 🙂