6

In interface builder I can get a "Vertical Space" that matches the "standard" spacing by 'pinning':

enter image description hereenter image description here

In the visual constraint language I can accomplish the same thing with:

V:[top]-[bottom]

How do I add standard spacing between two views in code?

I'm looking for something like this that might appear in a UIViewController:

NSLayoutConstraint *spacing = ???
[self.view addConstraint spacing];
Rich Apodaca
  • 28,316
  • 16
  • 103
  • 129
  • Why can't you use the visual format "in code", or is this just a curiosity question (which is fine by me!) – jrturton Oct 19 '12 at 18:41
  • @jrturton, all of my other constraints are in code. I'm doing this because I found this statement in the documentation: "There are constraints that cannot be expressed in visual format syntax, although most of the constraints that are useful in real user interfaces can be. One useful constraint that cannot be expressed is a fixed aspect ratio (for example, imageView.width = 2 * imageView.height). " Until I know what I'm doing and all of the limitations of the visual language become clear, I wanted to do everything in code first. – Rich Apodaca Oct 19 '12 at 19:10

3 Answers3

6

As of iOS 11.0 (released in 2017), there are methods that use the system spacing:

@interface NSLayoutXAxisAnchor (UIViewDynamicSystemSpacingSupport)
/* Constraints of the form,
 receiver [= | ≥ | ≤] 'anchor' + 'multiplier' * system space, 
 where the value of the system space is determined from information available from the anchors.
 The constraint affects how far the receiver will be positioned trailing 'anchor', per the effective user interface layout direction.
 */
- (NSLayoutConstraint *)constraintEqualToSystemSpacingAfterAnchor:(NSLayoutXAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));
- (NSLayoutConstraint *)constraintGreaterThanOrEqualToSystemSpacingAfterAnchor:(NSLayoutXAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));
- (NSLayoutConstraint *)constraintLessThanOrEqualToSystemSpacingAfterAnchor:(NSLayoutXAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));

@end

@interface NSLayoutYAxisAnchor (UIViewDynamicSystemSpacingSupport)
/* Constraints of the form,
 receiver [= | ≥ | ≤] 'anchor' + 'multiplier' * system space, 
 where the value of the system space is determined from information available from the anchors.
 The constraint affects how far the receiver will be positioned below 'anchor'. 
 If either the receiver or 'anchor' is the firstBaselineAnchor or lastBaselineAnchor of a view with text content
 then the spacing will depend on the fonts involved and will change when those do.
 */
- (NSLayoutConstraint *)constraintEqualToSystemSpacingBelowAnchor:(NSLayoutYAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));
- (NSLayoutConstraint *)constraintGreaterThanOrEqualToSystemSpacingBelowAnchor:(NSLayoutYAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));
- (NSLayoutConstraint *)constraintLessThanOrEqualToSystemSpacingBelowAnchor:(NSLayoutYAxisAnchor *)anchor multiplier:(CGFloat)multiplier __attribute__((warn_unused_result)) API_AVAILABLE(macos(11.0),ios(11.0),tvos(11.0));
@end

In Swift, you could use them like this:

let topView: UIView = ...
let bottomView: UIView = ...

bottomView.topAnchor
    .constraint(equalToSystemSpacingBelow: topView.bottomAnchor, multiplier: 1)
    .isActive = true

let leadingView: UIView = ...
let trailingView: UIView = ...

trailingView.leadingAnchor
    .constraint(equalToSystemSpacingAfter: leadingView.trailingAnchor, multiplier: 1)
    .isActive = true
rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • 5
    Isn't that just hard coding a space of 8? I think OP is after some system constant or keyword to describe the standard spacing. – jrturton Oct 19 '12 at 18:43
  • @jrturton I could not find a constant for it in the header files. – rob mayoff Oct 19 '12 at 18:44
  • @jrturton, If there is a system constant that expresses the standard spacing, that would be a good option. But I'd rather not use the number 8 directly. – Rich Apodaca Oct 19 '12 at 19:11
  • @robmayoff neither can I. Speaking of auto layout, I'd really appreciate your input on http://stackoverflow.com/questions/12943107/how-do-i-adjust-the-anchor-point-of-a-calayer-when-auto-layout-is-being-used, it would seem to tick several of your speciality boxes? – jrturton Oct 19 '12 at 19:25
2

Mixing and matching visual format constraints and the more verbose single constraint creation style (what I think you are referring to when you say "in code") is fine - in fact, in the WWDC talks about auto layout, the "preferred" order for you to create constraints was stated as:

  • Interface builder
  • Visual format
  • Single constraint style

Unless you need the extra power and flexibility that the single constraint style gives you (and there are lots of places where visual format doesn't work, in my experience with it so far), you should use the visual format. It sounds like you're approaching the list above from the bottom up, instead of the top down.

If you want to lay out views with standard spacing, and you're not using IB, then the visual format would make sense to use. As Rob says, there isn't a constant for "standard" spacing available, and you're making much more work for yourself by insisting on single constraints for everything.

jrturton
  • 118,105
  • 32
  • 252
  • 268
  • I ended up going mixed visual format style with one exception - a relative size constraint that can't be expressed in anything other than code. This cleaned up the constraint code considerably. Good call. – Rich Apodaca Oct 20 '12 at 15:41
1

Since the time this question was posted, constraint APIs were released for using the standard system spacing defaults:

Apple has sample code putting this in use, Creating Self-Sizing Table View Cells.

Curiosity
  • 544
  • 1
  • 15
  • 29