Lawrence413 Lawrence413 - 2 months ago 25
Swift Question

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?

Answer

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.