0

I run the below code on a button press, however the bottom constraint does not seem to be obeyed. The subview (bandCardView) overflows the bottom of the parent view (formVw). How can I make these constraints obeyed?

 @objc private func cardBtnTouch(){
        self.bandAccountView?.bankBtn.setSelected(selected: false)
        self.bandAccountView?.cardBtn.setSelected(selected: true)

        self.bandAccountView?.selectLbl.isHidden = true
        for subview in self.bandAccountView!.formVw.subviews{
            subview.removeFromSuperview()
        }
        self.bandAccountView!.formVw.addSubview(bandCardView!)
        self.bandAccountView!.formVw.addConstraint(NSLayoutConstraint(item: self.bandAccountView!.formVw, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: bandCardView!, attribute: NSLayoutAttribute.top, multiplier: 1.0, constant: 0.0))
        self.bandAccountView!.formVw.addConstraint(NSLayoutConstraint(item: bandCardView!, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.bandAccountView!.formVw, attribute: NSLayoutAttribute.bottom, multiplier: 1.0, constant: 0.0))
        self.bandAccountView!.formVw.addConstraint(NSLayoutConstraint(item: bandCardView!, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.bandAccountView!.formVw, attribute: NSLayoutAttribute.leading, multiplier: 1.0, constant: 0.0))
        self.bandAccountView!.formVw.addConstraint(NSLayoutConstraint(item: self.bandAccountView!.formVw, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: bandCardView!, attribute: NSLayoutAttribute.trailing, multiplier: 1.0, constant: 0.0))
    }
steventnorris
  • 5,656
  • 23
  • 93
  • 174
  • (Sometimes, idk when or why it's needed, but for some customViews you need it)....at the end of each of your constraints write `isActive = true`. Also make sure you have `translatesAutoresizingMaskIntoConstraints` set tot `false`. See if it works – mfaani May 19 '17 at 16:33
  • @Honey It was the autoresizing mask on the subviews. I always forget that part. If you submit and answer, I'll accept. – steventnorris May 19 '17 at 16:36
  • Also if you're not supporting iOS 8 then you can avoid using this verbose way of creating constraints and instead use `topAnchor`, `bottomAnchor`, etc. See [here](https://useyourloaf.com/blog/pain-free-constraints-with-layout-anchors/) or just see my question [here](https://stackoverflow.com/questions/44008908/label-showing-top-of-screen-instead-of-being-on-the-inputaccessoryview) – mfaani May 19 '17 at 16:37
  • see my edit about the relationship between the views – mfaani May 19 '17 at 20:44

1 Answers1

2

make sure you have translatesAutoresizingMaskIntoConstraints set to false.

Also after iOS 9 there is an easier way of writing your constraints.

Add a single constraint without any constant:

self.bandAccountView!.formVw.addConstraint(formVw.topAnchor.constraint(equalTo:
 bandCardView.topAnchor)

Add a single constraint with a constant:

self.bandAccountView!.formVw.addConstraint(formVw.topAnchor.constraint(equalTo: 
bandCardView.topAnchor, constant: 10)

Add multiple constraints:

self.bandAccountView!.formVw.addConstraints([formVw.topAnchor.constraint(equalTo:
 bandCardView.topAnchor),formVw.bottomAnchor.constraint(equalTo:
 bandCardView.bottomAnchor),formVw.leadingAnchor.constraint(equalTo: 
 bandCardView.leadingAnchor),formVw.trailingAnchor.constraint(equalTo:
 bandCardView.trailingAnchor)]

NOTE:

if you ever wrote:

self.bandAccountView!.formVw.leadingAnchor.constraint(equalTo:
formVw.leadingAnchor, constant: 0)

then you have actually forgot to "add/activate the constraint". To fix it you either have to do:

self.bandAccountView!.formVw.leadingAnchor.constraint(equalTo:
formVw.leadingAnchor, constant: 0).isActive = true

OR

let leadingConstraint = self.bandAccountView!.formVw.leadingAnchor.constraint(equalTo:
formVw.leadingAnchor, constant: 0)
leadingConstraint.isActive = true // do this whenever you need
leadingConstraint.isActive = false // if you don't need it...

or simply do like the first snippet


Additionally the relation between bandAccountView & formVw are instance--instance variable and they way you're doing it isn't good. It's much better to do the constraints in it's own class or create a custom init that would only adjust the constants for you.

mfaani
  • 33,269
  • 19
  • 164
  • 293