23

According to the Cocoa Auto Layout Guide, I can use a dash in the visual constraint format language to "denote the standard Aqua space:"

[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"[a]-[b]"
                                                             options:0
                                                             metrics:nil
                                                               views:viewDict]];

However, I can't seem to find an NSLayout... constant or method that allows me to do the same thing if I'm building a constraint without using the visual format language:

[self addConstraint:[NSLayoutConstraint constraintWithItem:a
                                                 attribute:NSLayoutAttributeTrailing
                                                 relatedBy:NSLayoutRelationEqual
                                                    toItem:b
                                                 attribute:NSLayoutAttributeLeading
                                                multiplier:1.0f
                                                  constant:<# ??? #>]];

Is there a constant (or another value or method) that I can use to define the Aqua space in such a situation?

Tim
  • 59,527
  • 19
  • 156
  • 165

3 Answers3

32

I've found the "standard Aqua space" to be 8.0 between sibling views, and 20.0 between a view and its superview.

NSView* view = [NSView new] ;
NSLayoutConstraint* constraintWithStandardConstantBetweenSiblings = [NSLayoutConstraint constraintsWithVisualFormat:@"[view]-[view]"  options:0  metrics:nil  views:NSDictionaryOfVariableBindings(view) ] [0] ;
CGFloat standardConstantBetweenSiblings = constraintWithStandardConstantBetweenSiblings.constant ;    // 8.0

NSView* superview = [NSView new] ;
[superview addSubview:view] ;
NSLayoutConstraint* constraintWithStandardConstantBetweenSuperview = [NSLayoutConstraint constraintsWithVisualFormat:@"[view]-|"  options:0  metrics:nil  views:NSDictionaryOfVariableBindings(view) ] [0] ;
CGFloat standardConstantBetweenSuperview = constraintWithStandardConstantBetweenSuperview.constant ;    // 20.0
John Sauer
  • 4,411
  • 1
  • 25
  • 33
10

For iOS users:

#import "NSLayoutConstraint+StandardOffsets.h"

@implementation NSLayoutConstraint (StandardOffsets)

+ (CGFloat)standardConstantBetweenSiblings
{
    static CGFloat value;

    if(!isnormal(value)) {
        UIView *view = [UIView new] ;
        NSLayoutConstraint* constraintWithStandardConstantBetweenSiblings = [NSLayoutConstraint constraintsWithVisualFormat:@"[view]-[view]"  options:0  metrics:nil  views:NSDictionaryOfVariableBindings(view) ] [0] ;
        value = constraintWithStandardConstantBetweenSiblings.constant ;    // 8.0
    }
    return value;
}

+ (CGFloat)standardConstantBetweenSuperview
{
    static CGFloat value;

    if(!isnormal(value)) {
        UIView *view = [UIView new] ;
        UIView *superview = [UIView new] ;
        [superview addSubview:view] ;
        NSLayoutConstraint* constraintWithStandardConstantBetweenSuperview = [NSLayoutConstraint constraintsWithVisualFormat:@"[view]-|"  options:0  metrics:nil  views:NSDictionaryOfVariableBindings(view) ] [0] ;
        value = constraintWithStandardConstantBetweenSuperview.constant ;    // 20.0
    }
    return value;
}

@end

PS: I entered a bugreport that no constant is offered in the header files!

David H
  • 40,852
  • 12
  • 92
  • 138
  • 1
    strangely the method `standardConstantBetweenSuperview` returns a value **0.0** sometimes instead of **20.0**. Any idea why this is happening? – GoGreen Feb 23 '15 at 05:56
  • @GoGreen In ios8? Things changed with it there are margins now - something like that. – David H Feb 23 '15 at 12:51
  • I checked only in iOS8, but even though if margins are considered, the constant value should never be **0.0** right? – GoGreen Feb 24 '15 at 04:09
5

Based on John Sauer's answer, I wound up writing a couple methods on an NSLayoutConstraint category to find the constants:

  • +standardAquaSpaceConstraintFromItem:toItem: returns a single NSLayoutConstraint constructed using the visual format language; it asserts that the array of constraints generated from the format has exactly one item, then gets that item and gives it back.
  • +standardAquaSpaceFromItem:toItem: pulls the constant out of the constraint from the previous method and returns it as a CGFloat.

This way, I can either get the constant value myself if I need to do computations, or just get a single layout constraint with the right spacing (e.g. for assigning to a constraint @property or directly adding to my view).

Community
  • 1
  • 1
Tim
  • 59,527
  • 19
  • 156
  • 165
  • Where are these methods? Can I use them? – Ky - Aug 22 '16 at 15:57
  • @BenLeggiero: the actual implementation belongs to my employer, unfortunately, so I can't post it up here. However, the better solution nowadays is probably to use the anchor-based constraint methods; see NSLayoutAnchor (and on iOS, UILayoutGuide). – Tim Aug 22 '16 at 18:29