Search code examples
iosswiftautolayoutnslayoutconstraintuislider

Programmed Slider Constraint is Not Updating


I have am attempting to learn how to populate a view in my storyboard with sliders and buttons, programmatically. I am trying, currently, to get one programmed slider to adhere to a programmed NSLayoutConstraint

Here is my code:

let centerXConstraint =  NSLayoutConstraint(item: self.volumeSliderP, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.centerX, multiplier: 1.0, constant: 10.0)

self.view.addConstraint(centerXConstraint)

I should mention, that when I substitute the first item for a slider which already exists on the view (which was placed via Storyboard, with it's own constraints also placed with IB/Storyboard), it does updated correctly with the above NSLayoutConstraint code. Also, I have been able to update my programmed volumeSliderP with custom code to change it's handle and rotate it to vertical successfully.

What step am I missing to allow this NSLayoutConstraint code to work upon my programmed slider?

Thank you for any help!


Solution

  • When working with constraints in code, you need to do two (maybe three) things, regardless of control type:

    • Set the translatesAutoresizingMaskIntoConstraints to false.

    Failure to do so will set off constraint conflicts, which will appear in the console log. I usually create an extension to UIView for this:

    public func turnOffAutoResizing() {
        self.translatesAutoresizingMaskIntoConstraints = false
        for view in self.subviews as [UIView] {
            view.translatesAutoresizingMaskIntoConstraints = false
        }
    }
    

    Then in viewDidLoad (after adding my subviews) I simply add a line:

    view.turnOffAutoResizing()
    

    As explained in the linked Apple doc, if you have label and a text field, the text field will expand to fit the label without the need for setting widths. A UISlider does not have an intrinsic width but it does have an intrinsic height.

    • So in your case you need to not only set position, it needs to define the width.

    A combination of top and leading will yield enough for the layout engine to know "where" and "height", but not "width". Same would go if you defined "centerX" and something - you didn't list any code - for the Y factor (top, bottom, centerY).

    If I'm stating this clearly, you should be able to see that the engine will know enough to say (in frame coordinates) "start the slider at X/Y, height is XX points (it has intrinsic height), but how long should it be?"

    I typically set either top, leading, and trailing... or top, centerX, and width. But it varies with the need.