Je posais les contraintes d'un bouton en utilisant un storyboard. J'ai vu une option, "Identifier" dans les propriétés de la contrainte.
Je veux faire référence à cette contrainte, changer sa valeur dans le code, déplacer un objet.
Comment puis-je obtenir une référence à cette NSLayoutContraint
à partir de cet identifiant?.
J'ai lu la documentation, c'était écrit comme ça
@interface NSLayoutConstraint (NSIdentifier)
/* For ease in debugging, name a constraint by setting its identifier, which will be printed in the constraint's description.
Identifiers starting with UI and NS are reserved by the system.
*/
@property (nullable, copy) NSString *identifier NS_AVAILABLE_IOS(7_0);
@end
Alors j'ai réalisé que c'est à des fins de débogage.
Et si je veux l'obtenir et l'utiliser? J'ai vu ce lien, mais aucune réponse satisfaisante n'a été donnée: Comment obtenir l'identifiant de NSLayoutConstraint par son pointeur?
Dans Swift 3 ,
let filteredConstraints = button.constraints.filter { $0.identifier == "identifier" }
if let yourConstraint = filteredConstraints.first {
// DO YOUR LOGIC HERE
}
Swift 3
J'ai écrit une extension rapide NSView qui gère cela très bien.
extension NSView {
func constraint(withIdentifier: String) -> NSLayoutConstraint? {
return self.constraints.filter { $0.identifier == withIdentifier }.first
}
}
Usage:
if let c = button.constraint(withIdentifier: "my-button-width") {
// do stuff with c
}
Je suppose que vous avez un point de vente configuré pour le bouton afin que vous puissiez y trouver une référence. Alors, commencez par récupérer les contraintes de la vue à partir de votre bouton. Parcourez ensuite le tableau et comparez à chaque itération la propriété identifer de chaque contrainte avec la valeur que vous avez entrée dans Interface Builder. On dirait que vous codez en Objective-C, donc l'exemple de code Objective-C est ci-dessous. Remplacez @ "identificateur" par la valeur que vous avez définie dans Interface Builder.
NSArray *constraints = [button constraints];
int count = [constraints count];
int index = 0;
BOOL found = NO;
while (!found && index < count) {
NSLayoutConstraint *constraint = constraints[index];
if ( [constraint.identifier isEqualToString:@"identifier"] ) {
//save the reference to constraint
found = YES;
}
index++;
}
J'ai simplifié la recherche et ajouté dans la liste des superviews d'ancêtres:
+ (NSLayoutConstraint *) findConstraintNamed:(NSString *)identifierTarget startWith:(UIView *)aView;
{
// walk upward from item through ancestors
UIView *currentView = aView;
while (currentView != nil)
{
NSArray *constraints = [currentView constraints];
NSInteger foundConstraintIndex = [constraints indexOfObjectPassingTest:^BOOL(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
return [((NSLayoutConstraint *)obj).identifier isEqualToString:identifierTarget];
}];
if (foundConstraintIndex != NSNotFound)
{
return constraints[foundConstraintIndex];
}
// not found, so walk up the ancestor chain
currentView = currentView.superview;
}
return nil; // not found anywhere in item or ancestors! :(
}
Pour redimensionner un ensemble de boutons dans un conteneur de vue commun, cela fonctionne. Chaque sous-vue/bouton doit utiliser un identifiant commun (par exemple, "hauteur").
@IBAction func btnPressed(_ sender: UIButton) {
for button in self.btnView.subviews{
for constraint in button.constraints{
if constraint.identifier == "height"{
constraint.constant = constraint.constant == 0 ? 30:0
}
}
}
UIView.animate(withDuration: 0.3) { () -> Void in
self.view.layoutIfNeeded()
}
}