6

I have a slider inside a table view cell and I'm trying to set the text of a label to the value of the slider. However, the text isn't setting to the changed slider values. What am I doing wrong?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = UITableViewCell()

    if indexPath.section == 0 {

        let slider = UISlider(frame: CGRectMake(0, 0, 320, 44))
        slider.userInteractionEnabled = true
        slider.minimumValue = 1
        slider.maximumValue = 100
        slider.value = 50
        slider.continuous = true
        cell.addSubview(slider)
        println(cell.bounds)

        let label = UILabel(frame: CGRectMake(260, -20, 100, 20))
        var theValue = Int(slider.value)
        label.text = "\(theValue)" + "mi."
        cell.addSubview(label)
 }
  • You are setting the current value in the `cellForRowAtIndexPath`, but it is not getting updated because your are not implementing `valueChanged` for the slider. – Caleb Aug 11 '15 at 21:55
  • Do I do that with an addTarget that calls a function called valueChanged? –  Aug 11 '15 at 21:56
  • Yes, but you will need to have access to the label as well. There are a couple ways you can achieve this. – Caleb Aug 11 '15 at 22:00

4 Answers4

5

You can do it as you have using some tricks, first of all you need to set the target for the UISlider as some as suggested, the other point is get the selected row, which you can achieve saving in the tag property the indexPath.row like in the following code:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell

    let slider = UISlider(frame: CGRectMake(0, 0, 100, 44))
    slider.userInteractionEnabled = true
    slider.minimumValue = 1
    slider.maximumValue = 100
    slider.value = 50
    slider.continuous = true

    // set the target to respond to changes.
    slider.addTarget(self, action: "sliderValueChanged:", forControlEvents: UIControlEvents.ValueChanged)

    // save the indexPath.row
    slider.tag = indexPath.row
    cell.addSubview(slider)


    let label = UILabel(frame: CGRectMake(105, 0, 100, 20))
    var theValue = Int(slider.value)
    label.text = "\(theValue)" + "mi."
    cell.addSubview(label)

    return cell
}

The another problem is set the UILabel text , which you can achieve by getting the exactly view inside the cell, like in the following code:

func sliderValueChanged(sender: AnyObject) {

    var slider = sender as! UISlider
    let cell = self.tableView.cellForRowAtIndexPath(NSIndexPath(forRow: slider.tag, inSection: 0)) as UITableViewCell!

    // If you know the exactly index
    // var label = cell.subviews[4] as! UILabel
    // label.text = "\(slider.value)"

    // assuming you have only one `UILabel` inside your cell
    for view in cell.subviews {
        if let label = view as? UILabel {
            label.text = "\(slider.value)"
        }
    }
}

In the above code I only set the exactly number inside the UITableViewCell for purpose of show the way, but the strongly recommended way is iterate through all the UIView and find your UILabel like in the method proposed in this question Find UILabel in UIView in Swift because the number can change.

As some people said before, is more easy set a Custom Cell all through Interface Builder, but it's up to you.

I hope this help you.

Community
  • 1
  • 1
Victor Sigler
  • 23,243
  • 14
  • 88
  • 105
  • Is this in a TableView Controller? I am using View Controller with Table View added. What do you suggest? I am having 3 sections in all. –  Aug 11 '15 at 22:56
  • Yes , but doesn't matter you can set the `@IBOutlet` to your `UITableView` and change the name according. – Victor Sigler Aug 11 '15 at 22:58
  • Hm, I'm getting the following error: '_UITableViewCellSeparatorView' (0x199842680) to 'UILabel' (0x19983fe30). Any ideas? –  Aug 11 '15 at 23:19
  • Yes of course, as I said in my answer before, I set the number according my `UITableViewCell`, but you need to find it as I said in my answer or just set the number, See updated answer to clarify doubts. – Victor Sigler Aug 11 '15 at 23:24
2

Generally you should add an action to your slider :

slider.addTarget(self, action: "sliderValueDidChange:", forControlEvents: .ValueChanged)

func sliderValueDidChange(sender:UISlider!)
{
    println("value--\(sender.value)")
}

as described here : http://www.apptuitions.com/programmatically-creating-uiview-uislider-uiswitch-using-swift/

** As you need to change label and use slider's value in any cell, separately, You have to use custom TableViewCell class and define your slider, label and action in it, easily.

** MY RECOMMENDATION: Use storyBoard and then easily design your view and use customized TableViewCell class.

a sample table view cell class for you ( similar to one in my own project ) :

class CustomCell: UITableViewCell {

    @IBOutlet weak var slider: UISlider!
    @IBOutlet weak var label: UILabel!

    @IBAction func sliderChanged(sender: AnyObject) {
    // set label text to slider.value here
    }

}
Sina KH
  • 563
  • 4
  • 16
  • I'd like to use StoryBoard but I need spacing between my sections on table view. Is this possible in StoryBoard? –  Aug 11 '15 at 22:13
  • You just need to override UITableViewDataSource functions.. Here is what you need: http://stackoverflow.com/questions/30364067/space-between-sections-in-uitableview – Sina KH Aug 11 '15 at 22:17
1

You are missing action on slider drag. slider.addTarget(self, action: "sliderValueDidChange", forControlEvents: .ValueChanged)

func sliderValueDidChange(sender:UISlider!){
    println("value--\(sender.value)")
    label.text = String(sender.value)
}

You can use slider.superview or store index in tag of the slider in order to get the reference to cell to which slider belongs and access label.

Better solution will be to create custom class for the cell.

Sameer
  • 201
  • 2
  • 4
1

Add this in your cellForRowAtIndexPath function:

slider.addTarget(self, action: "sliderValueChanged:", forControlEvents: .ValueChanged)
label.tag = 1

You can use this to update the label:

func sliderValueChanged(sender: AnyObject)
{
    var position: CGPoint = sender.convertPoint(CGPointZero, toView: self.tableView)
    if let indexPath = self.tableView.indexPathForRowAtPoint(position) {
        //get your cell here
        let cell = tableView.cellForRowAtIndexPath(indexPath)
        //update label
        for view in cell.subviews {
           if let label = view as? UILabel {
              if label.tag == 1 {
                 label.text! = "\((sender as! UISlider).value)"
              }
           } 
        }
    }
}

OR

You can do what others have mentioned and create a Custom UITableViewCell, add a slider and a label, and create IBOutlets for them.

Caleb
  • 5,548
  • 3
  • 25
  • 32