user3608914
user3608914

Reputation: 136

Getting nslayoutconstraints from UIView

after i have set up the constraints using anchor properties, such as this.

pageControl.anchorWithFixedHeight(nil, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: view.trailingAnchor, topConstant: 0, leadingConstant: 0, bottomConstant: 0, trailingConstant: 0, heightConstant: 30)

where anchorWithFixedHeight is just a helper function like the following:

func anchorWithFixedHeight(_ top: NSLayoutYAxisAnchor? = nil, leading: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, trailing: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leadingConstant: CGFloat = 0, bottomConstant: CGFloat = 0, trailingConstant: CGFloat = 0, heightConstant: CGFloat = 0) -> [NSLayoutConstraint] {

    translatesAutoresizingMaskIntoConstraints = false


    if let top = top {
        anchors.append(topAnchor.constraint(equalTo: top, constant: topConstant))
    }

    if let leading = leading {
        anchors.append(leadingAnchor.constraint(equalTo: leading, constant: leadingConstant))
    }

    if let bottom = bottom {
        anchors.append(bottomAnchor.constraint(equalTo: bottom, constant: bottomConstant))
    }

    if let trailing = trailing {
        anchors.append(trailingAnchor.constraint(equalTo: trailing, constant: trailingConstant))
    }

    anchors.append(heightAnchor.constraint(equalToConstant: heightConstant))

}

Now, let's say i wish to get the bottom anchor constraint to change its property, how can i achieve that?

Thanks in advance

Edit: The anchors here is an array of NSlayoutContraint. My current method works in such a way that i append all the needed constraints into this array, then get whichever constraint, for example bottom anchor constraint from this array.

However, i felt that the solution is not eloquent enough. Thus, was wondering if there is any other better approach.

Upvotes: 2

Views: 992

Answers (1)

rob mayoff
rob mayoff

Reputation: 385600

Let's clean up the signature of your method first. Since the constants are useless without the corresponding anchors, let's pass them together in tuples. We should also name the function after what it returns, which is constraints, not anchors.

If you want access to the constraints by what they constrain, we can do that in a type-safe way by returning a dictionary whose key type is NSLayoutAttribute and whose value type is NSLayoutConstraint. Thus we will call this new method like this:

let root = UIView()
let view = UIView()
root.addSubview(view)

let constraints = view.helperConstraints(
    leading: (root.leadingAnchor, 20),
    bottom: (root.bottomAnchor, 10),
    trailing: (root.trailingAnchor, 20),
    heightConstant: 30)

// Activate all the new constraints.
NSLayoutConstraint.activate(Array(constraints.values))

// Change the constant of the bottom constraint.
constraints[.bottom]!.constant = 40

The implementation isn't that different from yours:

extension UIView {

    func helperConstraints(
        top: (NSLayoutYAxisAnchor, CGFloat)? = nil,
        leading: (NSLayoutXAxisAnchor, CGFloat)? = nil,
        bottom: (NSLayoutYAxisAnchor, CGFloat)? = nil,
        trailing: (NSLayoutXAxisAnchor, CGFloat)? = nil,
        heightConstant: CGFloat? = nil) -> [NSLayoutAttribute: NSLayoutConstraint] {

        translatesAutoresizingMaskIntoConstraints = false
        var constraints = [NSLayoutAttribute: NSLayoutConstraint]()

        if let (anchor, constant) = top {
            constraints[.top] = topAnchor.constraint(equalTo: anchor, constant: constant)
        }

        if let (anchor, constant) = leading {
            constraints[.leading] = leadingAnchor.constraint(equalTo: anchor, constant: constant)
        }

        if let (anchor, constant) = bottom {
            constraints[.bottom] = bottomAnchor.constraint(equalTo: anchor, constant: constant)
        }

        if let (anchor, constant) = trailing {
            constraints[.trailing] = trailingAnchor.constraint(equalTo: anchor, constant: constant)
        }

        if let constant = heightConstant {
            constraints[.height] = heightAnchor.constraint(equalToConstant: constant)
        }

        return constraints
    }

}

Upvotes: 3

Related Questions