web-dev-qa-db-fra.com

Obtenez une référence à NSLayoutConstraint à l'aide de l'ensemble d'identifiants dans le storyboard

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.

Screenshot of constraint's properties

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?

12
Sam Shaikh

Dans Swift 3 ,

 let filteredConstraints = button.constraints.filter { $0.identifier == "identifier" }
 if let yourConstraint = filteredConstraints.first {
      // DO YOUR LOGIC HERE
 }
22
Venk

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
}
9
quemeful

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++;
}
8
strwils

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!  :(    
}
0
software evolved

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()
    }
}
0
Craig Jarman