4

So, I thought the following was equivalent?

# This is how I usually do
contentView.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
contentView.topAnchor.constraint(equalTo: topAnchor, constant: 5).isActive = true
contentView.rightAnchor.constraint(equalTo: rightAnchor, constant: -5).isActive = true
contentView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5).isActive = true

# This is what I tried. I expected the same result..
layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
contentView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
contentView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true

Though I appear to be wrong. How would I get the 5 margin between the containerView and the parent using margins, constraints and anchors?

netdigger
  • 3,659
  • 3
  • 26
  • 49

3 Answers3

7

I found a solution by reading this question: Auto Layout: layoutMarginsGuide.

There seems to be an issue when setting layoutMargins from the init.

Though, instead of setting layoutMargins in viewDidMoveToSuperView I put it in updateConstraints instead, which also worked fine.

So the code is now:

override init(frame: CGRect) {
    super.init(frame: frame)
    contentView.leftAnchor.constraint(equalTo: layoutMarginsGuide.leftAnchor).isActive = true
    contentView.topAnchor.constraint(equalTo: layoutMarginsGuide.topAnchor).isActive = true
    contentView.rightAnchor.constraint(equalTo: layoutMarginsGuide.rightAnchor).isActive = true
    contentView.bottomAnchor.constraint(equalTo: layoutMarginsGuide.bottomAnchor).isActive = true
}

override func updateConstraints() {
    super.updateConstraints()
    layoutMargins = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}

which then had the same effect as:

contentView.leftAnchor.constraint(equalTo: leftAnchor, constant: 5).isActive = true
contentView.topAnchor.constraint(equalTo: topAnchor, constant: 5).isActive = true
contentView.rightAnchor.constraint(equalTo: rightAnchor, constant: -5).isActive = true
contentView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -5).isActive = true
Community
  • 1
  • 1
netdigger
  • 3,659
  • 3
  • 26
  • 49
  • Not sure that it matters in this case, but in general, `super.updateConstraints()` should be called at the end of the implementation: [Apple Documentation](https://developer.apple.com/documentation/uikit/uiview/1622512-updateconstraints) – BlueSolrac Jul 12 '18 at 18:31
1

It seems that setting layoutMargins in updateConstraints() works, but with the following caveat:

override func updateConstraints() {
    super.updateConstraints()
    layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
}

The above code would fail to update the margins because the new value is the same as the system default. So to be safe, first reset the margins to zero:

override func updateConstraints() {
    super.updateConstraints()
    layoutMargins = .zero
    layoutMargins = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 8)
}

Also, if your goal is to set the initial margins to .zero, it's probably a good idea to first set them to a non-zero value, just to make sure the view is notified of the change.

Davor Bauk
  • 21
  • 4
-2

Objective-C:

[contentView.leftAnchor constraintEqualToAnchor:contentView.superview.leftAnchor constant:5].active = YES;
[contentView.rightAnchor constraintEqualToAnchor:contentView.superview.rightAnchor constant:5].active = YES;
[contentView.topAnchor constraintEqualToAnchor:contentView.superview.topAnchor constant:5].active = YES;
[contentView.bottomAnchor constraintEqualToAnchor:contentView.superview.bottomAnchor constant:5].active = YES;

Swift 3:

contentView.leftAnchor.constraint(equalTo: contentView.superview?.leftAnchor, constant: 5).isActive = true
contentView.rightAnchor.constraint(equalTo: contentView.superview?.rightAnchor, constant: 5).isActive = true
contentView.topAnchor.constraint(equalTo: contentView.superview?.topAnchor, constant: 5).isActive = true
contentView.bottomAnchor.constraint(equalTo: contentView.superview?.bottomAnchor, constant: 5).isActive = true
Said Hasanein
  • 320
  • 1
  • 5
  • 1
    If you read the question you'll see that that's exactly how u said I'm doing it right now, and I want to know how to get it working with layoutMarginGuides instead – netdigger Nov 05 '16 at 16:05