iosswiftnslayoutconstraintnslayoutanchor

Is layoutMarginsGuide seems to be kind of excessive?


When i was trying to create layout constraints, i read about NSLayoutAnchor class. They said:

Note

UIView does not provide anchor properties for the layout margin attributes. Instead, the layoutMarginsGuide property provides a UILayoutGuide object that represents these margins. Use the guide’s anchor properties to create your constraints

Ok. But simultaneously I crated anchor properties for the layout margin properties without UILayoutGuide property.

     let inputsContainerView = UIView()
    inputsContainerView.backgroundColor = UIColor.white
    inputsContainerView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(inputsContainerView)

    //need x,y,width,height constraints
    inputsContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0).isActive = true
    inputsContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0).isActive = true
    inputsContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
    inputsContainerView.heightAnchor.constraint(equalToConstant: 150).isActive = true

So then why do we need UILayoutGuide object? And it turns out UIView does provide anchor properties for the layout margin attributes? Please if someone know anything I would very appreciated.


Solution

  • It depends on your design requirements.

    layoutMarginsGuide documentation states:

    A layout guide representing the view’s margins. Use this layout guide’s anchors to create constraints with the view’s margin.

    Where Layout Margins is basically just the safe area of a view:

    Safe areas help you place your views within the visible portion of the overall interface. UIKit-defined view controllers may position special views on top of your content. For example, a navigation controller displays a navigation bar on top of the underlying view controller’s content. Even when such views are partially transparent, they still occlude the content that is underneath them.

    For self.view, the visible portion of the overall interface would exclude the areas taken up by status bar, navigation bar, tab bar, etc.
    For a normal UIView, the default padding is 8px.

    So basically, if you want someView to be constrained within the safe area / margin of otherView, then you will reference otherView's layoutMarginsGuide anchors.
    If not, then just otherView's anchors are enough.

    1. Example (with layoutMarginsGuide):

    let textField = UILabel()
    textField.text = "Using Layout Margins Guide Anchors"
    textField.backgroundColor = UIColor.red
    textField.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(textField)
    
    var constraints = [NSLayoutConstraint]()
    //textfield's top edge = self.view's margin's top edge
    constraints.append(textField.topAnchor.constraint(equalTo: self.view.layoutMarginsGuide.topAnchor))
    
    //textfield's leading edge = self.view's margin's leading edge
    constraints.append(textField.leadingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.leadingAnchor))
    
    //textfield's trailing edge = self.view's margin's trailing edge
    constraints.append(textField.trailingAnchor.constraint(equalTo: self.view.layoutMarginsGuide.trailingAnchor))
    
    //Apply the constraints
    NSLayoutConstraint.activate(constraints)
    

    Output:

    On layoutMarginsGuide

    Observation:


    2. Example (without layoutMarginsGuide):

    let textField = UILabel()
    textField.text = "Without Layout Margins Guide Anchors"
    textField.backgroundColor = UIColor.red
    textField.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(textField)
    
    var constraints = [NSLayoutConstraint]()
    //textfield's top edge = self.view's top edge
    constraints.append(textField.topAnchor.constraint(equalTo: self.view.topAnchor))
    
    //textfield's leading edge = self.view's leading edge
    constraints.append(textField.leadingAnchor.constraint(equalTo: self.view.leadingAnchor))
    
    //textfield's trailing edge = self.view's trailing edge
    constraints.append(textField.trailingAnchor.constraint(equalTo: self.view.trailingAnchor))
    
    //Apply the constraints
    NSLayoutConstraint.activate(constraints)
    

    Output: On View Anchors alone

    Observation:


    Finally, it depends on your requirement.
    Sometimes you should use it, sometimes you could use it, sometimes you just don't need to use it.

    PS: Now, whether you base it on the UIView's anchors or it's layoutMarginsGuide anchors, it will respond to device rotation or any other layout changes automatically.