Search code examples
swiftuilabeluislider

UISlider no subviews in ViewDidLoad()


I want to put a UILabel on the UISlider's thumb.

My code is based on this: Another SO question

The problem is that with that code, there's no text on the thumb before you change the value. So I made a few modifications. I made the label a global variable and I configure it in viewDidLoad(). Then I just change the text when the slider changes value.

The ACTUAL problem is this(code in viewDidLoad()):

let thumbView = mySlider.subviews.last
label.frame = (thumbView?.bounds)!

mySlider's subviews array is empty. Therefore it creates a crash since I unwrap a nil value.

I don't understand why that happens since the view is fully initialized.

Why is mySlider.subviews empty? What am I missing? Does anyone know how can I fix this? Is there any other way of placing the label in the middle of the thumb?


Solution

  • mySlider.subviews.last is not a reliable method to get the center of the thumbImage. It wasn't mention anywhere in the docs. I personally think is quite hacky to do it that way.

    However, to get the center of the slider you could calculate base on the value of the slider using a combine of trackRectForBounds and thumbRectForBounds.

    This should work for you:

    @IBAction func sliderValueChanged(slider: UISlider) {
        let trackRect = slider.trackRectForBounds(slider.bounds)
        let thumbRect = slider.thumbRectForBounds(slider.bounds, trackRect: trackRect, value: slider.value)
    
        sliderLabel.center = CGPointMake(thumbRect.origin.x + thumbRect.size.width / 2 + slider.frame.origin.x, slider.frame.origin.y + thumbRect.size.height / 2)
    }
    

    Basically what this does is to first compute the rect of the track then use it to compute the thumbRect. Lastly set the center taking into consideration the width and height of the slider and thumb size.

    Do remember to set your label text alignment to center.