17

我正在尝试使用自动布局为 Cocoa 中的控件设置动画。

现在,我可以设置[[constraint animator] setConstant:newWidth];,这很有效。但是我怎样才能得到正确的约束呢?

有了[self constraints]你可以获得所有约束,在这种情况下我可以选择constraints[0],但约束的顺序可能会有所不同。

我怎么能确定我总是有正确的约束?约束在 Interface Builder 中设置。我已经看到您可以向其中添加 IBOutlet,但似乎没有必要。


我的解决方案

谢谢,效果很好。我写了一个小类。


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
4

3 回答 3

39

每个约束都有一个属性[constraint firstAttribute] 它返回一个枚举 NSLayoutAttribute

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

    NSLayoutAttributeNotAnAttribute = 0
};

所以你可以检查 NSLayoutAttributeWidth 的宽度。

示例代码:

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];
于 2012-12-13T10:18:09.060 回答
5

这是在 Xcode 8.2.1 和 macOS 10.12.2 上测试的 swift 3 版本。

该代码显示了如何获取按钮的宽度和高度约束,但您可以从NSLayoutAttribute枚举中过滤您想要的任何内容。

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)
于 2017-01-12T03:41:37.613 回答
0

我写了一个可重用的扩展:(Swift 4.1)

/**
 * Utils when working with constraints
 */
extension NSLayoutConstraint{
    /**
     * Returns all constraints of kinds
     * EXAMPLE: NSLayoutConstraint.ofKind(rect.immediateConstraints, kinds: [.width,.height]) //width, height
     */
    static func ofKind(_ constraints:[NSLayoutConstraint],kinds:[NSLayoutAttribute]) -> [NSLayoutConstraint]{
        return kinds.map { kind in
            return constraints.filter { constraint in
                return constraint.firstAttribute == kind
            }
        }.flatMap({$0})//flattens 2d array to 1d array
    }
}
于 2018-05-05T12:53:36.820 回答