Getting an existing NSLayoutConstraint for the width?

11,845

Solution 1

Every contraint has an attribute [constraint firstAttribute] It returns an enum NSLayoutAttribute

typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
    NSLayoutAttributeLeft = 1,
    NSLayoutAttributeRight,
    NSLayoutAttributeTop,
    NSLayoutAttributeBottom,
    NSLayoutAttributeLeading,
    NSLayoutAttributeTrailing,
    NSLayoutAttributeWidth,
    NSLayoutAttributeHeight,
    NSLayoutAttributeCenterX,
    NSLayoutAttributeCenterY,
    NSLayoutAttributeBaseline,

    NSLayoutAttributeNotAnAttribute = 0
};

so you can check NSLayoutAttributeWidth for width.

Sample code:

NSArray constraints = [self constraints];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", NSLayoutAttributeWidth];
NSArray *filteredArray = [constraints filteredArrayUsingPredicate:predicate];
if(filteredArray.count == 0){
      return nil;
}
NSLayoutConstraint *constraint =  [constraints objectAtIndex:0];

Solution 2

Here is the swift 3 version tested on Xcode 8.2.1 and macOS 10.12.2.

The code shows how to get a button's width and height constraints, but you could filter whatever you want from NSLayoutAttribute enum.

let cons = signInButton.constraints.filter {
    $0.firstAttribute == NSLayoutAttribute.width || $0.firstAttribute == NSLayoutAttribute.height /// or other from `NSLayoutAttribute`
}
// do something with the constraints array, e.g.
NSLayoutConstraint.deactivate(cons)
Share:
11,845

Related videos on Youtube

IluTov
Author by

IluTov

I'm a Swiss developer. Just a guy who enjoys programming.

Updated on September 16, 2022

Comments

  • IluTov
    IluTov over 1 year

    I'm trying to animate a control in Cocoa with auto layout.

    Now, I can set [[constraint animator] setConstant:newWidth];, which works. But how can I get the right constraint?

    With [self constraints] you can get all the constraints, and in this case I can just select constraints[0], but the order of the constraints may vary.

    How can I be certain I always have the right constraint? The constraints are set in Interface Builder. I have seen that you can add a IBOutlet to it, but it doesn't seem necessary.


    My solution

    Thanks, it worked great. I wrote a little category.


    NSView+NSLayoutConstraintFilter.h

    #import <Cocoa/Cocoa.h>
    
    @interface NSView (NSLayoutConstraintFilter)
    - (NSLayoutConstraint *)constraintForAttribute:(NSLayoutAttribute)attribute;
    - (NSArray *)constaintsForAttribute:(NSLayoutAttribute)attribute;
    @end
    

    NSView+NSLayoutConstraintFilter.m

    #import "NSView+NSLayoutConstraintFilter.h"
    
    @implementation NSView (NSLayoutConstraintFilter)
    
    - (NSArray *)constaintsForAttribute:(NSLayoutAttribute)attribute {
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"firstAttribute = %d", attribute];
        NSArray *filteredArray = [[self constraints] filteredArrayUsingPredicate:predicate];
    
        return filteredArray;
    }
    
    - (NSLayoutConstraint *)constraintForAttribute:(NSLayoutAttribute)attribute {
        NSArray *constraints = [self constaintsForAttribute:attribute];
    
        if (constraints.count) {
            return constraints[0];
        }
    
        return nil;
    }
    
    @end
    
  • IluTov
    IluTov over 11 years
    Great answer, worked like a charm, I wrote a category, take a look.
  • funmania
    funmania over 7 years
    if(filteredArray.count == 0){ return nil; } NSLayoutConstraint *constraint = [constraints objectAtIndex:0]; this can be avoided by using NSLayoutConstraint *constraint = [constraints lastIndex];
  • Sentry.co
    Sentry.co almost 6 years
    When I use this, some constraints are missing