JamesG JamesG - 21 days ago 11
Swift Question

Swift: Changing HeightAnchor Programmatically

I am following this video tutorial: https://www.youtube.com/watch?v=4rNtIeC_dsQ

I am struggling to get the height of the container view to change when I choose a different option in the UI Segment Control

approx around 17:51 in the video

I declared the var like so:

var inputsContainerHeightAnchor: NSLayoutConstraint?


for the constraints, I now have:

inputContainerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
inputContainerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
inputContainerView.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -60).isActive = true
inputContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerHeightAnchor?.isActive = true


for the segment control I have:

func handleLoginRegisterChange() {

let title = segmentedLoginRegisterControl.titleForSegment(at: segmentedLoginRegisterControl.selectedSegmentIndex)

loginRegisterButton.setTitle(title, for: .normal)

inputsContainerHeightAnchor?.constant = segmentedLoginRegisterControl.selectedSegmentIndex == 0 ? 100 : 150



}


The segment control is set up like so:

lazy var segmentedLoginRegisterControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["Login", "Register"])
sc.tintColor = .white
sc.selectedSegmentIndex = 1
sc.translatesAutoresizingMaskIntoConstraints = false
sc.addTarget(self, action: #selector(handleLoginRegisterChange), for: .valueChanged)
return sc
}()


I am using Xcode Version 8.1

However when I run this is the simulator, the input controller view is 100. and it does not change when I click any of the segments.

Can someone see anything I have missed?

Answer

The part you failed to do properly happens starting at 16:50 in the video. But we can figure out the problem from the code you posted. These lines are fishy:

inputContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerHeightAnchor?.isActive = true

The first of those lines creates an instance of NSLayoutConstraint, but doesn't activate it and doesn't store it in a variable. So the constraint is immediately destroyed. It has no effect aside from wasting time and battery power.

The second of those lines mentions the variable inputsContainerHeightAnchor, which looks a lot like it should reference the constraint created in the prior line. But the prior line didn't assign anything to that variable. If nothing else assigned a value to that variable, then the variable is nil. Since it's dereferenced using ? instead of !, the second statement does nothing if the variable contains nil.

You probably meant to write this:

inputsContainerHeightAnchor = inputContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerHeightAnchor?.isActive = true

The first line stores the new constraint in the variable, and the second line activates the new constraint. This is what happens in the video starting around 16:50. What you probably missed is at about 17:15, he says “we'll get rid of the let” while he copies the variable name from his instance variable declaration and pastes it over the text let constraint. The line wraps on his screen, his indentation is incorrect, and he does the copy and paste with keyboard shortcuts, so it's hard to follow. You probably thought he just deleted the text let constraint =. (This is why when I make videos I try to avoid keyboard shortcuts.)

However, it would be even better to write these two lines like this:

inputsContainerHeightAnchor = inputContainerView.heightAnchor.constraint(equalToConstant: 150)
inputsContainerHeightAnchor!.isActive = true

When you are sure that a variable should not be nil, and being nil is a programming error, then use ! to dereference it. The program will stop (in the debugger if running under Xcode) on that line if the variable contains nil. If you (and the author of the video) had written it this way, you might have found the error much sooner, because the program would never have gotten past that second line until you fixed the error.