Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting an existing NSLayoutConstraint for the width?

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
like image 233
IluTov Avatar asked Dec 13 '12 09:12

IluTov


People also ask

What is UIView encapsulated layout width?

If you see the error message contains UIView-Encapsulated-Layout-Width , which means your constraints relative to width conflict with it. For example, you set label constrains: [ leading , trailing , bottom , top ] or [ CenterX , leading , bottom , top ] leading trailing and CenterX are for width.

How do I update the layout in Swift?

If you want to force a layout update, call the setNeedsLayout() method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded() method.

How do you add constraints in Uikit?

Select the options for aligning the selected views, and click the Add Constraints button.


2 Answers

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];
like image 195
Sunil Pandey Avatar answered Oct 12 '22 16:10

Sunil Pandey


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)
like image 5
longkai Avatar answered Oct 12 '22 16:10

longkai